|
|
1.1 root 1: .fp 1 B1
2: .fp 2 B2
3: .fp 3 B3
4: .TM 1982-11272-1 11173 39199-11
5: .ND "February 10, 1982"
6: .TL
7: Dynamic Statement Counting:
8: A Manual for Users and Owners
9: .AU MH2C522 7214
10: P.J. Weinberger
11: .AI
12: .MH
13: .OK
14: Program Testing
15: .AB
16: Although time profiling is a standard
17: .UX
18: tool,
19: until now there has been no convenient way to find out
20: how often each line of a C or Fortran program is executed
21: when the program is run.
22: This memo describes a simple tool which gives statement and
23: instruction execution counts at a modest cost (about 50%)
24: in run-time efficiency.
25: The programs works on VAXes, and can be modified to work
26: on other machines with adequate address space.
27: Any user can install and use the programs without
28: affecting the compilers, assembler, or loader, and
29: without bothering the system administrators.
30: .PP
31: The typical output
32: .DS
33: .nf
34: .ft CW
35: 1 main(argc)
36: 1 { int i;
37: 1 if(argc > 3)
38: 0 exit(1);
39: 1 for(i = 0; i < 100; i++)
40: 67 if(i % 3 == 0)
41: 34 i++;
42: 67 }
43: .ft P
44: .fi
45: .DE
46: shows how often each line was executed;
47: alternative forms would show that
48: of the 18 machine instructions, exactly one was never executed,
49: or would say how many instructions were executed.
50: .AE
51: .CS 6 0 6 0 0 1
52: .NH
53: What is Execution Counting?
54: .PP
55: Dynamic execution counting provides counts of how often each part
56: of a program was executed.
57: The results of several tests can be combined, or the data
58: can be collected one run at a time.
59: Information about your program can be presented in several forms.
60: .NH 2
61: Summarizing Test Coverage
62: .PP
63: Condensed summary data like
64: .DS
65: .ft CW
66: .nf
67: 1962519ie 390i 175ine 471439bbe 106bb 55bbne /usr/sys/pseki/uba.c
68: 16893220ie 334i 49ine 5562730bbe 115bb 21bbne /usr/sys/pseki/clock.c
69: .fi
70: .ft P
71: .DE
72: says that of the 390 instructions in \f2uba.c\fP 175 were never executed,
73: and 49 of the 334 instructions in \f2clock.c\fP were never executed.
74: Section 4.1 explains the output fully.
75: Data like this summarizes test coverage.
76: .NH 2
77: Source Statement Counts
78: .PP
79: Compiling the program
80: .KS
81: .nf
82: .ft CW
83: main()
84: { int i;
85: for(i = 0; i < 100; i++)
86: if(i % 3 == 0)
87: i++;
88: }
89: .fi
90: .ft P
91: .KE
92: with execution counting enabled (see Section 2), and running it once,
93: would give the following source statement counts.
94: .KS
95: .nf
96: .ft CW
97: 1 main()
98: 1 { int i;
99: 1 for(i = 0; i < 100; i++)
100: 67 if(i % 3 == 0)
101: 34 i++;
102: 67 }
103: .fi
104: .ft P
105: .KE
106: Interpreting the output is discussed in section 4.
107: .NH
108: The Three Roads to Invoking Execution Counting
109: .PP
110: The statement count profiler works on C or Fortran programs.
111: There are two parts to it,
112: one to compile the program with execution counting enabled,
113: and the other, named \f2lprint\fP, to print the results.
114: The first part, a program named
115: .I bb ,
116: modifies the assembly language produced by the compilers
117: by inserting counting instructions at the beginning of each basic block.
118: (A basic block is a set of instructions that have to be executed
119: if any one of them is.)
120: The program described here works only on VAXes,
121: but it is easy to modify it to work on almost any machine
122: with an adequate address space.
123: .PP
124: The ease of using the program depends on how easy it is to
125: get the local system to interpolate \f2bb\fP
126: into the compilation process.
127: There are three sorts of systems.
128: .NH 2
129: Good Systems
130: .PP
131: On friendly well-run systems the \f2cc\fP and \f2f77\fP commands
132: know about \f2bb\fP.
133: The \f2-L\fP (for Line-counting) flag enables execution counts, as in
134: .DS
135: .nf
136: .I
137: cc -L main.c subr.c lib.o -o xxx
138: .R
139: or
140: .I
141: cc -L -c main.c; cc -L -c subr.c;
142: cc -L main.o subr.o lib.o -o xxx
143: .R
144: .fi
145: .DE
146: or similarly for \f2f77\fP.
147: .PP
148: In this example, statement counts will be generated for \f2main.c\fP
149: and for \f2subr.c\fP,
150: but not for \f2lib.c\fP,
151: unless it too had been compiled with \f2-L\fP.
152: .NH 2
153: Adequate Systems
154: .PP
155: An adequate system is one which has the counting software,
156: but the software is not integrated into \f2cc\fP.
157: The distributed software contains two shell scripts,
158: .I lcomp
159: and
160: .I lcc .
161: The former takes any combination of C and Fortran
162: source, \f2.o\fP files, and \f2.s\fP files, and produces an
163: .I a.out
164: file, rather like \f2cc\fP, except that it does not produce
165: \&\f2.o\fP files.
166: .DS
167: .I
168: lcomp main.c subr.c lib.o
169: .R
170: .DE
171: has the same effect as the first \f2cc\fP example above,
172: except that it produces its output in \f2a.out\fP,
173: rather than in \f2xxx\fP.
174: .PP
175: .I lcc
176: is used to prepare \f2.o\fP files,
177: so that count profiling can be used with separate compilations.
178: The second \f2cc\fP example above would be
179: .DS
180: .I
181: lcc main.c; lcc subr.c; lcomp main.o subr.o lib.o
182: .R
183: .DE
184: on merely adequate systems.
185: .NH 2
186: Not Yet Adequate Systems
187: .PP
188: Your system is less adequate if it does not have this software.
189: You can get the counting software by sending mail to me at
190: \f2rabbit!pjw\fP, and I will send it to you.
191: It can be installed and used without any special help from
192: system administrators.
193: .NH
194: What it Leaves Behind, and Why
195: .PP
196: After programs have been compiled using either of the techniques
197: described above, there will be some new files,
198: named \f2main.sL\fP and \f2subr.sL\fP.
199: When the \f2a.out\fP executes
200: it appends to a file \f2prof.out\fP in the current directory.
201: .PP
202: The \f2prof.out\fP file contains information on how often each
203: basic block was executed.
204: The various \f2.sL\fP files contain information correlating
205: basic blocks with source lines, and with the instructions in
206: the basic block.
207: .PP
208: Do not move the \f2.sL\fP files, since they are found by their
209: full path names.
210: .PP
211: Since the \f2prof.out\fP is cumulative, it must be empty the
212: first time a new version of a program is run.
213: The compilation procedures try to remove a lingering \f2prof.out\fP,
214: but the user should check carefully.
215: .NH
216: Getting Output
217: .PP
218: After you run your program one or more times,
219: run the \f2lprint\fP command to produce a listing.
220: The listing contains only those files that had some program in them
221: executed, and that were compiled with count profiling.
222: Here is a simple example.
223: .KS
224: \f(CW
225:
226: .nf
227: 1 #include "stdio.h"
228: 1 main()
229: 1 { int n;
230: 81 while((n = getchar()) != EOF) putchar(n);
231: 1 }
232: .fi
233: \fP
234: .KE
235: .PP
236: The basic information is that the program \f2main\fP was executed
237: once, and the loop was executed 81 times.
238: The non-executable lines seem to have been executed also, but that
239: is an artifact.
240: Each line in the source corresponds to zero, one, or several basic
241: blocks, and basic blocks can span several lines of source.
242: To each line, the program attributes the next basic block in
243: the assembly language, which is usually the correct one when there
244: is one basic block corresponding to a line.
245: The count of 1 on the closing curly brace above is not an artifact;
246: unoptimized programs contain a jump to the end at their entry point.
247: These points can be seen more clearly in the following example.
248: .KS
249: \f(CW
250:
251: .nf
252: 1 #include "stdio.h"
253: 1 main()
254: 1 { int n, i;
255: 1 for(
256: 1 i = 0; /* line 5 */
257: 1 (n = getchar()) != EOF; i++)
258: 110 putchar(n);
259: 1 exit(0);
260: 1 }
261: .fi
262: \fP
263: .KE
264: For reasons known best to itself, the C compiler
265: believes that no code is generated for line 5, so that the
266: initialization code, which is executed only once, is associated
267: with the next line.
268: This flaw would be seen if the program were single-stepped using
269: \f2sdb\fP, since \f2bb\fP and \f2sdb\fP use exactly the
270: same line-numbers generated by the compiler.
271: .PP
272: By saying \f2lprint -i\fP the user gets the following, on the same
273: data as above.
274: .KS
275: \f(CW
276:
277: .nf
278: 0i #include "stdio.h"
279: 0i main()
280: 1i { int n, i;
281: 0i for(
282: 0i i = 0;
283: 1105i (n = getchar()) != EOF; i++)
284: 770i putchar(n);
285: 2i exit(0);
286: 3i }
287: .fi
288: \fP
289: .KE
290: The numbers on the left are the number of instructions executed
291: for each line.
292: The strange attribution of the initialization code to line 6
293: is still present, but it doesn't hide the 1104 other instructions
294: executed in line 6.
295: .PP
296: The command \f2lprint -i -p\fP gets both statement counts and
297: instruction counts.
298: .NH 2
299: Other Options
300: .PP
301: \f2lprint\fP has two other options.
302: \f2lprint -c\fP compresses the \f2prof.out\fP file.
303: After each execution of the profiled program, count data is
304: written at the end of \f2prof.out\fP.
305: Big programs generate a lot of counting data,
306: so that compressing it back to the amount generated by one run
307: will save space, and make \f2lprint\fP run faster when
308: it is producing listings
309: .PP
310: \f2lprint -s\fP produces summary data, as in
311: .KS
312: \f(CW
313:
314: 1949ie 31i 5ine 691bbe 12bb 1bbne /usr/pjw/prof/a.c
315:
316: \fP
317: .KE
318: This line says that \f2/usr/pjw/prof/a.c\fP contains
319: 31 assembly instructions and 12 basic blocks.
320: During testing (or whatever produced \f2prof.out\fP)
321: there were 1949 instruction executions, and 5 of the 31 instructions
322: were never executed.
323: There were 691 basic blocks executed, and 1 of the 12 basic
324: blocks was never executed.
325: This option is most useful for summarizing test coverage
326: in programs which are made of a lot of files.
327: .NH 2
328: Another Peculiarity
329: .PP
330: The order of the listing may puzzle the user.
331: The files are listed in inverse order of first use.
332: .NH
333: Installing the Distributed Programs
334: .PP
335: The distribution (mailed out as described in section 2.3)
336: contains four C programs, a \f2makefile\fP,
337: the two shell scripts \f2lcomp\fP and \f2lcc\fP,
338: some manual pages, possibly an up-to-date version of
339: this document, and a file that describes installation.
340: .PP
341: The two C programs \f2instr.c\fP and \f2bb.c\fP
342: are to be compiled together to make the program \f2bb\fP.
343: \f2bb\fP is the program that modifies the compiler's output
344: and leaves behind \f2.sL\fP files for \f2lprint\fP.
345: The shell scripts expect to find \f2bb\fP in the directory
346: whose name is the value of the shell variable \f2DIR\fP.
347: The C program \f2nexit.o\fP (obtained by compiling \f2nexit.c\fP)
348: must also be in \f2DIR\fP.
349: It must be loaded in place of the standard \f2exit\fP
350: routine to get the \f2prof.out\fP file written when the
351: program being profiled terminates.
352: \f2lcomp\fP runs \f2bb\fP and loads \f2nexit.o\fP.
353: .PP
354: The two shell files and \f2lprint\fP (obtained by compiling
355: \f2lprint.c\fP) should be put in \f2/usr/bin\fP,
356: or some place where the user community can find them.
357: .NH 2
358: Does It Work?
359: .PP
360: Try it on one of the example programs given in the first section.
361: If you do not get through \f2lcomp\fP because \f2bb\fP fails,
362: perhaps you aren't on a VAX.
363: A more likely hypothesis is that the assembly language put out
364: by your version of the C compiler is incomprehensible to the program.
365: This should not happen with any version of
366: .UX
367: now running on VAXes.
368: .PP
369: Now run the \f2a.out\fP, and type \f2lprint\fP.
370: If you get a listing with counts, all is well.
371: If you get nothing, look at the \f2.sL\fP file.
372: If there are lines like \f2a.c: 1\fP interspersed with
373: the assembly language, and if there is a \f2prof.out\fP
374: file, but \f2lprint\fP won't produce output,
375: let me know.
376: If there are no such lines, then \f2bb\fP failed to find
377: symbol table information describing line numbers in the
378: C compiler's output.
379: This will happen if your C compiler is sufficiently non-standard.
380: The subroutine that recognizes file names and line numbers in
381: \f2bb.c\fP will have to be changed.
382: .PP
383: The author would like to hear about problems.
384: .NH
385: Summary
386: .PP
387: The statement counting code works on all languages which
388: use the assembler: C, Fortran, and (on some systems) Pascal.
389: It works on VAXes, an earlier version was easily converted to
390: work on Motorola 68000s by Tom London, and it will work on 3Bs
391: and 370s soon.
392: It can be installed and used without affecting any of the software
393: vital to the system and without the help or approval of system
394: administrators.
395: In particular it renders obsolete a previous test coverage processor
396: for C [1].
397: .NH
398: Esoterica
399: .NH 2
400: Programs that don't Terminate
401: .PP
402: Some programs, like the operating system, or network daemons,
403: are not supposed to terminate, so \f2nexit\fP would never
404: be called, so the \f2prof.out\fP file would never be written.
405: Nonetheless it is desirable to be able to profile such programs.
406: .PP
407: Assuming that the programs have been compiled with the
408: counting code inserted by \f2bb\fP, the problem
409: is to get the counting data out of them periodically.
410: Distributed with the source is a file \f2sysprof.c\fP
411: which shows how to solve the problem with the kernel.
412: A subroutine with the same structure would have to be included
413: in a non-terminating user program,
414: and invoked either periodically or by a signal.
415: .NH 2
416: More Detailed Output
417: .PP
418: \f2lprint -a\fP prints intermediate data which
419: lists each instruction and how often it was executed.
420: Here is a Fortran example.
421: (C is exactly the same.)
422: The Fortran program \f2a.f\fP is
423: .KS
424: .nf
425: \f(CW
426: real a(100), b(100), x
427: integer i
428: do 10 i = 1, 100
429: a(i) = i
430: b(i) = i
431: 10 continue
432: x = 0
433: do 20 i = 1, 100
434: x = x + a(i) * b(i)
435: 20 continue
436: stop 12
437: end
438: \fP
439: .fi
440: .KE
441: The output from \f2lprint -a\fP is
442: .DS
443: \f(CW
444: .nf
445: a.f: 1
446: 1 subl2 $LF1,sp
447: 1 jmp L12
448: a.f: 2
449: a.f: 3
450: 1 movl $1,r11
451: 100 movl r11,v.1
452: a.f: 4
453: 100 cvtlf r11,r0
454: 100 movf r0,v.2+-4[r11]
455: a.f: 5
456: 100 cvtlf r11,r0
457: 100 movf r0,v.3+-4[r11]
458: a.f: 6
459: 100 incl r11
460: 100 cmpl r11,$100
461: 100 jleq L17
462: 1 movl r11,v.1
463: a.f: 7
464: 1 clrf v.4
465: a.f: 8
466: 1 movl $1,r11
467: 100 movl r11,v.1
468: a.f: 9
469: 100 mulf3 v.3+-4[r11],v.2+-4[r11],r0
470: 100 addf2 v.4,r0
471: 100 movf r0,v.4
472: a.f: 10
473: 100 incl r11
474: 100 cmpl r11,$100
475: 100 jleq L20
476: 1 movl r11,v.1
477: a.f: 11
478: 1 pushl $2
479: 1 pushl $L21
480: 1 calls $2,_s_stop
481: a.f: 12
482: 0 ret
483: 1 jmp L13
484: .fi
485: \fP
486: .DE
487: .PP
488: From this level of detail, it is possible to answer most
489: questions about the behavior of the program.
490: .SH
491: References
492: .LP
493: [1] Michael Lesk, A C Profiler for Test Case Verification. TM-80-1274-8.
494: .SG
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.