On Wed, Jan 16, 2019 at 11:43:12PM +0900, Akira Yokosawa wrote: > >From 87259dba261e59aba91f5e9b7943274567b200dd Mon Sep 17 00:00:00 2001 > From: Akira Yokosawa <akiyks@xxxxxxxxx> > Date: Wed, 16 Jan 2019 23:03:58 +0900 > Subject: [PATCH] debugging: Employ new scheme for code snippets > > In sh/awk code, it is not possible to put inline comments on > lines ending with "\". To avoid continuations, shorten variable > names in datablows.sh. > > As source files of snippets are searched under CodeSamples/, > put a symbolic link to utilities/datablows.sh under > CodeSamples/debugging. > > "grep -r" doesn't follow symbolic links, so use the "-R" option > instead. > > Signed-off-by: Akira Yokosawa <akiyks@xxxxxxxxx> > --- > Hi Paul, > > Another snippet scheme update. > > I'm wondering if you are OK with the shortening of variable names > in datablows.sh. It looks like almost impossible to properly put > a label as a comment to the line of the form: > > awk -v divisor=$divisor -v relerr=$relerr \ <-- this line > -v trendbreak=$trendbreak '{ > > , while keeping the script executable. > > Thoughts? Can't argue in this case. Applied and pushed, thank you! Thanx, Paul > Thanks, Akira > -- > CodeSamples/debugging/datablows.sh | 1 + > Makefile | 4 +- > debugging/debugging.tex | 196 +++++++++++++------------------------ > utilities/datablows.sh | 60 ++++++------ > utilities/gen_snippet_d.pl | 4 +- > 5 files changed, 105 insertions(+), 160 deletions(-) > create mode 120000 CodeSamples/debugging/datablows.sh > > diff --git a/CodeSamples/debugging/datablows.sh b/CodeSamples/debugging/datablows.sh > new file mode 120000 > index 0000000..cd04dd2 > --- /dev/null > +++ b/CodeSamples/debugging/datablows.sh > @@ -0,0 +1 @@ > +../../utilities/datablows.sh > \ No newline at end of file > diff --git a/Makefile b/Makefile > index b76eea0..6ef4629 100644 > --- a/Makefile > +++ b/Makefile > @@ -83,8 +83,8 @@ A2PING_GSCNFL := 0 > endif > endif > > -SOURCES_OF_SNIPPET_ALL := $(shell grep -r -l -F '\begin{snippet}' CodeSamples) > -SOURCES_OF_LITMUS := $(shell grep -r -l -F '\begin[snippet]' CodeSamples) > +SOURCES_OF_SNIPPET_ALL := $(shell grep -R -l -F '\begin{snippet}' CodeSamples) > +SOURCES_OF_LITMUS := $(shell grep -R -l -F '\begin[snippet]' CodeSamples) > SOURCES_OF_LTMS := $(patsubst %.litmus,%.ltms,$(SOURCES_OF_LITMUS)) > SOURCES_OF_SNIPPET := $(filter-out $(SOURCES_OF_LTMS),$(SOURCES_OF_SNIPPET_ALL)) $(SOURCES_OF_LITMUS) > GEN_SNIPPET_D = utilities/gen_snippet_d.pl utilities/gen_snippet_d.sh > diff --git a/debugging/debugging.tex b/debugging/debugging.tex > index 37d9022..0d5023f 100644 > --- a/debugging/debugging.tex > +++ b/debugging/debugging.tex > @@ -217,17 +217,11 @@ validation is just the right type of job for you. > Suppose that you are writing a script that processes the > output of the \co{time} command, which looks as follows: > > - \vspace{5pt} > - \begin{minipage}[t]{\columnwidth} > - \tt > - \scriptsize > - \begin{verbatim} > + \begin{VerbatimU} > real 0m0.132s > user 0m0.040s > sys 0m0.008s > - \end{verbatim} > - \end{minipage} > - \vspace{5pt} > + \end{VerbatimU} > > The script is required to check its input for errors, and to > give appropriate diagnostics if fed erroneous \co{time} output. > @@ -585,16 +579,10 @@ In some such cases, assertions can be helpful. > > Assertions are usually implemented in the following manner: > > -\vspace{5pt} > -\begin{minipage}[t]{\columnwidth} > -\tt > -\scriptsize > -\begin{verbatim} > - 1 if (something_bad_is_happening()) > - 2 complain(); > -\end{verbatim} > -\end{minipage} > -\vspace{5pt} > +\begin{VerbatimN} > +if (something_bad_is_happening()) > + complain(); > +\end{VerbatimN} > > This pattern is often encapsulated into C-preprocessor macros or > language intrinsics, for example, in the Linux kernel, this might > @@ -2124,41 +2112,39 @@ Similarly, interrupt-based interference can be detected via the > \path{/proc/interrupts} file. > > \begin{listing}[tb] > -{ \scriptsize > -\begin{verbbox} > - 1 #include <sys/time.h> > - 2 #include <sys/resource.h> > - 3 > - 4 /* Return 0 if test results should be rejected. */ > - 5 int runtest(void) > - 6 { > - 7 struct rusage ru1; > - 8 struct rusage ru2; > - 9 > - 10 if (getrusage(RUSAGE_SELF, &ru1) != 0) { > - 11 perror("getrusage"); > - 12 abort(); > - 13 } > - 14 /* run test here. */ > - 15 if (getrusage(RUSAGE_SELF, &ru2 != 0) { > - 16 perror("getrusage"); > - 17 abort(); > - 18 } > - 19 return (ru1.ru_nvcsw == ru2.ru_nvcsw && > - 20 ru1.runivcsw == ru2.runivcsw); > - 21 } > -\end{verbbox} > +\begin{linelabel}[ln:debugging:Using getrusage() to Detect Context Switches] > +\begin{VerbatimL} > +#include <sys/time.h> > +#include <sys/resource.h> > + > +/* Return 0 if test results should be rejected. */ > +int runtest(void) > +{ > + struct rusage ru1; > + struct rusage ru2; > + > + if (getrusage(RUSAGE_SELF, &ru1) != 0) { > + perror("getrusage"); > + abort(); > + } > + /* run test here. */ > + if (getrusage(RUSAGE_SELF, &ru2 != 0) { > + perror("getrusage"); > + abort(); > + } > + return (ru1.ru_nvcsw == ru2.ru_nvcsw && > + ru1.runivcsw == ru2.runivcsw); > } > -\centering > -\theverbbox > +\end{VerbatimL} > +\end{linelabel} > \caption{Using \tco{getrusage()} to Detect Context Switches} > -\label{lst:count:Using getrusage() to Detect Context Switches} > +\label{lst:debugging:Using getrusage() to Detect Context Switches} > \end{listing} > > Opening and reading files is not the way to low overhead, and it is > possible to get the count of context switches for a given thread > by using the \co{getrusage()} system call, as shown in > -Listing~\ref{lst:count:Using getrusage() to Detect Context Switches}. > +Listing~\ref{lst:debugging:Using getrusage() to Detect Context Switches}. > This same system call can be used to detect minor page faults (\co{ru_minflt}) > and major page faults (\co{ru_majflt}). > > @@ -2207,70 +2193,12 @@ thus far, then the next element is accepted and the process repeats. > Otherwise, the remainder of the list is rejected. > > \begin{listing}[tb] > -{ \scriptsize > -\begin{verbbox} > - 1 divisor=3 > - 2 relerr=0.01 > - 3 trendbreak=10 > - 4 while test $# -gt 0 > - 5 do > - 6 case "$1" in > - 7 --divisor) > - 8 shift > - 9 divisor=$1 > - 10 ;; > - 11 --relerr) > - 12 shift > - 13 relerr=$1 > - 14 ;; > - 15 --trendbreak) > - 16 shift > - 17 trendbreak=$1 > - 18 ;; > - 19 esac > - 20 shift > - 21 done > - 22 > - 23 awk -v divisor=$divisor -v relerr=$relerr \ > - 24 -v trendbreak=$trendbreak '{ > - 25 for (i = 2; i <= NF; i++) > - 26 d[i - 1] = $i; > - 27 asort(d); > - 28 i = int((NF + divisor - 1) / divisor); > - 29 delta = d[i] - d[1]; > - 30 maxdelta = delta * divisor; > - 31 maxdelta1 = delta + d[i] * relerr; > - 32 if (maxdelta1 > maxdelta) > - 33 maxdelta = maxdelta1; > - 34 for (j = i + 1; j < NF; j++) { > - 35 if (j <= 2) > - 36 maxdiff = d[NF - 1] - d[1]; > - 37 else > - 38 maxdiff = trendbreak * \ > - 39 (d[j - 1] - d[1]) / (j - 2); > - 40 if (d[j] - d[1] > maxdelta && \ > - 41 d[j] - d[j - 1] > maxdiff) > - 42 break; > - 43 } > - 44 n = sum = 0; > - 45 for (k = 1; k < j; k++) { > - 46 sum += d[k]; > - 47 n++; > - 48 } > - 49 min = d[1]; > - 50 max = d[j - 1]; > - 51 avg = sum / n; > - 52 print $1, avg, min, max, n, NF - 1; > - 53 }' > -\end{verbbox} > -} > -\centering > -\theverbbox > +\input{CodeSamples/debugging/datablows@xxxxxxxxx} > \caption{Statistical Elimination of Interference} > -\label{lst:count:Statistical Elimination of Interference} > +\label{lst:debugging:Statistical Elimination of Interference} > \end{listing} > > -Listing~\ref{lst:count:Statistical Elimination of Interference} > +Listing~\ref{lst:debugging:Statistical Elimination of Interference} > shows a simple \co{sh}/\co{awk} script implementing this notion. > Input consists of an x-value followed by an arbitrarily long list of y-values, > and output consists of one line for each input line, with fields as follows: > @@ -2305,44 +2233,58 @@ This script takes three optional arguments as follows: > which case the ``break'' will be ignored.) > \end{description} > > -Lines~1-3 of > -Listing~\ref{lst:count:Statistical Elimination of Interference} > -set the default values for the parameters, and lines~4-21 parse > +\begin{lineref}[ln:debugging:datablows:whole] > +Lines~\lnref{param:b}-\lnref{param:e} of > +Listing~\ref{lst:debugging:Statistical Elimination of Interference} > +set the default values for the parameters, and > +lines~\lnref{parse:b}-\lnref{parse:e} parse > any command-line overriding of these parameters. > -The \co{awk} invocation on lines~23 and~24 sets the values of the > +\end{lineref} > +\begin{lineref}[ln:debugging:datablows:whole:awk] > +The \co{awk} invocation on line~\lnref{invoke} sets the values of the > \co{divisor}, \co{relerr}, and \co{trendbreak} variables to their > \co{sh} counterparts. > -In the usual \co{awk} manner, lines~25-52 are executed on each input > +In the usual \co{awk} manner, > +lines~\lnref{copy:b}-\lnref{end} are executed on each input > line. > -The loop spanning lines~24 and~26 copies the input y-values to the > -\co{d} array, which line~27 sorts into increasing order. > -Line~28 computes the number of y-values that are to be trusted absolutely > +The loop spanning lines~\lnref{copy:b} and~\lnref{copy:e} copies > +the input y-values to the > +\co{d} array, which line~\lnref{asort} sorts into increasing order. > +Line~\lnref{comp_i} computes the number of y-values that are to be > +trusted absolutely > by applying \co{divisor} and rounding up. > > -Lines~29-33 compute the \co{maxdelta} value used as a lower bound on > +Lines~\lnref{delta}-\lnref{comp_max:e} compute the \co{maxdelta} > +value used as a lower bound on > the upper bound of y-values. > -To this end, lines~29 and~30 multiply the difference in values over > +To this end, line~\lnref{maxdelta} multiplies the difference in values over > the trusted region of data by the \co{divisor}, which projects the > difference in values across the trusted region across the entire > set of y-values. > However, this value might well be much smaller than the relative error, > -so line~31 computes the absolute error (\co{d[i] * relerr}) and adds > +so line~\lnref{maxdelta1} computes the absolute error (\co{d[i] * relerr}) > +and adds > that to the difference \co{delta} across the trusted portion of the data. > -Lines~32 and~33 then compute the maximum of these two values. > +Lines~\lnref{comp_max:b} and~\lnref{comp_max:e} then compute the maximum of > +these two values. > > -Each pass through the loop spanning lines~34-43 attempts to add another > +Each pass through the loop spanning lines~\lnref{add:b}-\lnref{add:e} > +attempts to add another > data value to the set of good data. > -Lines~35-39 compute the trend-break delta, with line~36 disabling this > +Lines~\lnref{chk_engh}-\lnref{break} compute the trend-break delta, > +with line~\lnref{chk_engh} disabling this > limit if we don't yet have enough values to compute a trend, > -and with lines~38 and~39 multiplying \co{trendbreak} by the average > +and with line~\lnref{mul_avr} multiplying \co{trendbreak} by the average > difference between pairs of data values in the good set. > -If line~40 determines that the candidate data value would exceed the > +If line~\lnref{chk_max} determines that the candidate data value would exceed the > lower bound on the upper bound (\co{maxdelta}) \emph{and} > -line~41 determines that the difference between the candidate data value > +that the difference between the candidate data value > and its predecessor exceeds the trend-break difference (\co{maxdiff}), > -then line~42 exits the loop: We have the full good set of data. > +then line~\lnref{break} exits the loop: We have the full good set of data. > > -Lines~44-52 then compute and print the statistics for the data set. > +Lines~\lnref{comp_stat:b}-\lnref{comp_stat:e} then compute and print > +the statistics for the data set. > +\end{lineref} > > \QuickQuiz{} > This approach is just plain weird! > @@ -2368,7 +2310,7 @@ Lines~44-52 then compute and print the statistics for the data set. > > Of course, it is possible to create a script similar to > that in > - Listing~\ref{lst:count:Statistical Elimination of Interference} > + Listing~\ref{lst:debugging:Statistical Elimination of Interference} > that uses standard deviation rather than absolute difference > to get a similar effect, > and this is left as an exercise for the interested reader. > diff --git a/utilities/datablows.sh b/utilities/datablows.sh > index 83d86d7..c4060c2 100644 > --- a/utilities/datablows.sh > +++ b/utilities/datablows.sh > @@ -34,49 +34,50 @@ > # > # Authors: Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx> > > -divisor=3 > -relerr=0.01 > -trendbreak=10 > -while test $# -gt 0 > +#\begin{snippet}[labelbase=ln:debugging:datablows:whole,commandchars=\!\@\%] > +div=3 #\lnlbl{param:b} > +rel=0.01 > +tre=10 #\lnlbl{param:e} > +while test $# -gt 0 #\lnlbl{parse:b} > do > case "$1" in > --divisor) > shift > - divisor=$1 > + div=$1 > ;; > --relerr) > shift > - relerr=$1 > + rel=$1 > ;; > --trendbreak) > shift > - trendbreak=$1 > + tre=$1 > ;; > esac > shift > -done > -# echo divisor: $divisor relerr: $relerr trendbreak: $trendbreak > +done #\lnlbl{parse:e} > +# echo divisor: $div relerr: $rel trendbreak: $tre #\fcvexclude > > -awk -v divisor=$divisor -v relerr=$relerr -v trendbreak=$trendbreak '{ > - for (i = 2; i <= NF; i++) > - d[i - 1] = $i; > - asort(d); > - i = int((NF + divisor - 1) / divisor); > - delta = d[i] - d[1]; > - maxdelta = delta * divisor; > - maxdelta1 = delta + d[i] * relerr; > - if (maxdelta1 > maxdelta) > - maxdelta = maxdelta1; > - for (j = i + 1; j < NF; j++) { > - if (j <= 2) > +awk -v divisor=$div -v relerr=$rel -v trendbreak=$tre '{#\lnlbl{awk:invoke} > + for (i = 2; i <= NF; i++) #\lnlbl{awk:copy:b} > + d[i - 1] = $i; #\lnlbl{awk:copy:e} > + asort(d); #\lnlbl{awk:asort} > + i = int((NF + divisor - 1) / divisor); #\lnlbl{awk:comp_i} > + delta = d[i] - d[1]; #\lnlbl{awk:delta} > + maxdelta = delta * divisor; #\lnlbl{awk:maxdelta} > + maxdelta1 = delta + d[i] * relerr; #\lnlbl{awk:maxdelta1} > + if (maxdelta1 > maxdelta) #\lnlbl{awk:comp_max:b} > + maxdelta = maxdelta1; #\lnlbl{awk:comp_max:e} > + for (j = i + 1; j < NF; j++) { #\lnlbl{awk:add:b} > + if (j <= 2) #\lnlbl{awk:chk_engh} > maxdiff = d[NF - 1] - d[1]; > else > - maxdiff = trendbreak * (d[j - 1] - d[1]) / (j - 2); > -# print "i: " i, "j: " j, "maxdelta: " maxdelta, "maxdiff: " maxdiff, "d[j] - d[j - 1]: " d[j] - d[j - 1] > - if (d[j] - d[1] > maxdelta && d[j] - d[j - 1] > maxdiff) > - break; > - } > - n = sum = 0; > + maxdiff = trendbreak * (d[j - 1] - d[1]) / (j - 2); #\lnlbl{awk:mul_avr} > +# print "i: " i, "j: " j, "maxdelta: " maxdelta, "maxdiff: " maxdiff, "d[j] - d[j - 1]: " d[j] - d[j - 1] #\fcvexclude > + if (d[j] - d[1] > maxdelta && d[j] - d[j - 1] > maxdiff) #\lnlbl{awk:chk_max} > + break; #\lnlbl{awk:break} > + } #\lnlbl{awk:add:e} > + n = sum = 0; #\lnlbl{awk:comp_stat:b} > for (k = 1; k < j; k++) { > sum += d[k]; > n++; > @@ -84,5 +85,6 @@ awk -v divisor=$divisor -v relerr=$relerr -v trendbreak=$trendbreak '{ > min = d[1]; > max = d[j - 1]; > avg = sum / n; > - print $1, avg, min, max, n, NF - 1; > -}' > + print $1, avg, min, max, n, NF - 1; #\lnlbl{awk:comp_stat:e} > +}' #\lnlbl{awk:end} > +#\end{snippet} > diff --git a/utilities/gen_snippet_d.pl b/utilities/gen_snippet_d.pl > index e07e58d..580e5ca 100755 > --- a/utilities/gen_snippet_d.pl > +++ b/utilities/gen_snippet_d.pl > @@ -23,9 +23,9 @@ my $re; > $snippet_key = '\begin{snippet}' ; > $snippet_key_ltms = '\begin[snippet]' ; > @ignore_re = ('\.swp$', '~$', '\#$') ; # to ignore backup of vim and emacs > -@fcvsources = `grep -l -r -F '$snippet_key' CodeSamples` ; > +@fcvsources = `grep -l -R -F '$snippet_key' CodeSamples` ; > @fcvsources = grep { not /\.ltms$/ } @fcvsources ; > -@fcvsources_ltms = `grep -l -r -F '$snippet_key_ltms' CodeSamples` ; > +@fcvsources_ltms = `grep -l -R -F '$snippet_key_ltms' CodeSamples` ; > foreach $re (@ignore_re) { > @fcvsources = grep { not /$re/ } @fcvsources ; > @fcvsources_ltms = grep { not /$re/ } @fcvsources_ltms ; > -- > 2.7.4 >