Analyzing Program Performance With Sun WorkShop

Compiling for tcov

To compile a program for code coverage, use the -xa option to the C compiler. Using a program named index.assist as an example, you compile for use with tcov with this command:

% cc -xa -o index.assist index.assist.c

You use the -a compiler option with the C++ or f77 compilers.

The C compiler generates an index.assist.d file, containing database entries for the basic blocks present in index.assist.c. When the program index.assist is run until completion, the compiler updates the index.assist.d file.


Note -

tcov works with both C and C++ programs, but tcov does not support files that contain #line or #file directives. tcov does not enable test coverage analysis of the code in the #include header files. Applications compiled with -xa (C), -a (other compilers), and +d (C++) run slower than normal. The +d option inhibits expansion of C++ inline functions, and updating the .d file for each execution takes considerable time.


The index.assist.d file is created in the directory specified by the environment variable TCOVDIR. If TCOVDIR is not set, index.assist.d is created in the current directory.

Having compiled index.assist.c, you could run index.assist:


% index.assist 
% ls *.d
index.assist.d

Now you could run tcov to produce a file containing the summaries of execution counts for each statement in the program. tcov uses the index.assist.d file to generate an index.assist.tcov file containing an annotated list of your code. The output shows the number of times each source statement is executed. At the end of the file, there is a short summary.


% tcov index.assist.c 
% ls *.tcov
index.assist.tcov

This small fragment of the C code from one of the modules of index.assist shows the insert_index_entry function, which is called so recursively.


			struct index_entry * 
11152		->	insert_index_entry(node, entry) 
			structindex_entry *node; 
			struct index_entry *entry; 
			{ 
				int result; 
				int level; 

				result = compare_entry(node, entry); 
				if (result == 0) {								/* exact match */ 
													/* Place the page entry for the duplicate */ 
												/* into the list of pages for this node */ 
59		->				insert_page_entry(node, entry->page_entry); 
						free(entry); 
						return(node); 
				} 

11093		->		if (result > 0)						/* node greater than new entry -- */ 
											/* move to lesser nodes */ 
3956		->				if (node->lesser != NULL) 
3626		->						insert_index_entry(node->lesser, entry); 
						else { 
330		->						node->lesser = entry; 
								return (node->lesser); 
						}
					else					/* node less than new entry -- */ 
										/* move to greater nodes */ 
7137		->				if (node->greater != NULL) 
6766		->						insert_index_entry(node->greater, entry); 
						else { 
371		->						node->greater = entry; 
								return (node->greater); 
						} 
			} 

The numbers to the side of the C code show how many times each statement was executed. The insert_index_entry function is called 11,152 times.

tcov places a summary like this at the end of the annotated program listing for index.assist.tcov:

   Top 10 Blocks
   
  Line  Count
  240  21563
  241  21563
  245  21563
  251  21563
  250  21400
  244  21299
  255  20612
  257  16805
  123  12021
  124  11962
   
 77 Basic blocks in this file
 55 Basic blocks executed
 71.43 Percent of the file executed
   
  439144 Total basic block executions
  5703.17 Average executions per basic block

A program compiled for code coverage analysis can be run multiple times (with potentially varying input); tcov can be used on the program after each run to compare behavior.