FunctionCheck V1.2 (Y. Perret, January 2000) I. Description II. Bugs III. The 'fncdump' program IV. Example V. Internal description VI. Licence VII. Contact VIII.Changes IX. ToDo list X. The 'fncaverage' program I. Description ---------------- FncCheck is a library which generates profiles for C/C++ programs. A profile is a list of informations about your functions, such as time spend in functions, number of calls and other things. To read more precise informations, please use the 'fncdump.info' file or the THML version, respectively in doc/ and doc/html/ dirs. In order to use FncCheck, you have to compile your .o files with '-finstrument-functions -g' switches (gcc V2.95.2 and higher). You have then to link your executable with the library 'libfnccheck.so' or the object 'fnccheck.o'. Note: if you use 'fnccheck.o', you have to add '-lm' flag. Note: the '-g' switch is not an obligation. But without it, you will not be able to use '-func+' and '-calls+' options. See the test/ dir for an example of compilation. Once compiled, make a complete execution of your program. It generates a 'fnccheck.out' file in the current directory (the exact name of the file is displayed at the end of execution). If your program performs 'forks()', each of your childs will generates a 'fnccheck.out_PID_OF_CHILD' for its execution. In order to see profile of your executable, use 'fncdump' program (see below for details on dumps). Controls available: The library uses a table for functions name and a stack to store functions calls. For speed reasons, these tables are allocated once at the beginning of the program (at 1024 and 1000000 resp.). It is possible to change these size by changing shell varaiables: * FNCCHK_STOP : if set, the lib is desactivated. * FNCCHK_STACKSIZE : the the size of the stack. * FNCCHK_NBFUNC : set the size of the functions table. * FNCCHK_OUTFILE : name of output file (default: './fnccheck.out'). * FNCCHK_DYNAMIC : if set, allows to increase tables size if needed. Can introduce bias in times computations. * FNCCHK_NOCHILD : if set, childs of the process are not dumped to file at all. * FNCCHK_TIME : set the time mode: "ext" -> external time (gettimeofday), "cpu" -> CPU time of process (clock()) Default value is "ext". * FNCCHK_DEBUG : ORed values of debug options. Values are: 2: display collisions for the hash table at the end 4: details on each fnccheck functions 8: details on treatments Note: FNCCHK_DEBUG has no effect if the lib is not compiled with debug mode ('make dfnccheck' instead of 'make fnccheck'). Note: the FNCCHK_PID variable is removed. Now, the default behavior of 'fnccheck' is to generates 'fnccheck.out' file for the starting process, and to generates 'fnccheck.out_PID' for childs. WARNING: a hash table is used to store functions during execution. Its size is computed using the initial size of the functions table. It is NOT (at this time) reallocated if functions table size is increased. Number of colisions in the hash-table will so increase too. Any invalid value make default values used instead. II. BUGS --------- No one known for V1.2 at this time. ----------------- |III. fncdump | ----------------- 'fncdump' is the program given with FncCheck which display profiles (it was named 'dump' in old versions). For each function is displayed: * the cycles detected: List of detected cycles during execution (with -cycles option). * the flat profile: - its total time (time between enter and exit of the function) - its local time (total time minus the time spend in child referenced functions) - corresponding '%' (regards to the total execution time) - the number of calls to the function - the average time per call (total time divided by # of calls) * MIN/MAX: List of min and max times for each functions. * functions details: If requested (-func-details), display the list of functions with their file and line number (must be compiled with '-g' option). * the call-graph: list of calls per function. For each function, the list of every functions which call it. Note: '-calls' option modify this list. For each function the list of the functions it call. Other informations are displayed: - the executable name - the execution total time - the kind of time used (EXT, CPU or SYS) - the number of 'realloc' performed (if allowed) - the final stack size - the number of functions - the number of non-displayed functions, due to option -no-unresolved - the number of non-displayed functions, due to option -no-spontaneous - the list of MIN and MAX time spend in each functions * Here is the --help of fncdump: Usage: fncdump exec [opts] or: fncdump -avg Opts: -sfile f : use 'f' as stat file instead of 'fnccheck.out' -sort n : sort mode. See at the end for details +sort n : sort mode (reverse). See at the end for details -no-spontaneous : dont print spontaneous called functions (dont apply to main) -no-unresolved : dont print unresolved symbols -calls : show 'called' functions instead of 'called by' +calls : show 'called' functions AND 'called by' -no-minmax : dont display MIN/MAX time for functions -nm : use 'nm' instead of 'libbfd'(1) to extract names -addr2line : use 'nm' instead of 'libbfd'(1) to extract names -func-details : add file/line for functions (not with '-nm') -call-details : add file/line for function calls (not with '-nm') -fullname : use full pathname for file/line info -only : just use functions that are in the comma separated list -not : dont use functions that are in the comma separated list -propagate : -only/-not is applied to childs -rpropagate : -only/-not is applied to callers -propagate : -only/-not is applied to childs -real-maxtime : use total execution time of displayed functions rather than total exec. time of all functions. -sum-profile a b c : sum profile files a and b into c (- means stdout) --help : this message --version : fnccheck/dump version --misc : author/contact/bugs --details : explanations about displayed informations Sort types: 1: sorted by 'Local time' 2: sorted by 'Total time' 3: sorted by 'Call number' 4: sorted by 'Function name' 5: sorted by 'No sort' The -avg usage gives you the average time spend in FncCheck treatments per each of your function. Note: the '-avg' switch now calls the 'fncaverage' program. You can use it directly. * 'exec' is the executable name. * '-sfile f' use 'f' stat. file instead of 'fnccheck.out'. * '+/-sort n' indicate the kind of sort (ascending/descending). * '-avg' display the average time spend in the library for each enter/exit of functions. * '-no-spontaneous' dont display spontaneous functions. Spontaneous functions are functions called by no one (dont apply to main). * '-no-unresolved' dont display functions with unresolved symbols. (this can append if you use optimization options in gcc, or using static constructors in C++). * '-calls' display 'called', instead 'called by'. * '+calls' display both 'called' and 'called by'. * '-no-minmax' remove MIN/MAX times displaying. * '-nm' force the use of 'nm' to extract symbol names. Using this option, you will not be able to use '-func-details' and '-call-details' * '-addr2line' force the use of 'addr2line' to extract symbol names, instead of 'libbfd' from GNU binutils (if compiled with BFD). * '-only' specify a list of functions name. Only these functions are considered in the output stats. * '-not' specify a list of functions name. These functions are removed from the output stats. * '-propagate' is used with '-only' and '-not'. It propagates functions to use or to remove using call-tree (a child of a referenced function is treated the same). * '-rpropagate' is the same than '-propagate', but the direction of propagation is "callers" instead of "childs". * '-func-details' displays a list of all functions with the file and the line from which they come from. * '-call-details' displays file and line of each call, in the 'called by' or 'calls' list. * '-real-maxtime' compute total execution time using the displayed list of functions instead of the total list of functions. It means that if you remove 'main' from the displayed list, the total execution time will be smaller than the real execution time of the program. Usefull when studying sub-parts of a program. * '-sum-profile' read the two profile files 'a' and 'b' and generates a new profile file called 'c' which is the sum of the stats from the two previous files. Using '-' for 'c' means that the new profile is send into stdout. 'a' and 'b' are closed BEFORE 'c' is opened, it is so possible to overwrite one of them by using the same name for 'c' and 'a' or 'b'. WARNING: if you sum two files from different programs or different compilations, generated stats will have few validity... IV. Example ------------ > gcc -c foo.c -finstrument-functions -g > gcc -o foo foo.o -lfnccheck (or gcc -o foo foo.c -finstrument-functions -g -lfnccheck) > foo FunctionCheck: starting (V1.2 by Hexasoft). FunctionCheck: all done (sfile: ./fnccheck.out). Dump display: > fncdump foo FunctionChecker V1.2 for gcc (by Y. Perret) Running profile data file version number 1.1.5 Cycles during execution: 1: Simple recursion: 'recurs' calls itself. Total time for this function: 0.000103 2: Cycle: cycle from 'recurs_a' to 'recurs_b' Total time for this cycle: 5.348654 3: Simple recursion: 'recurs_1s' calls itself. Total time for this function: 8.078811 General information: Profile for 'foo' Total execution time: 16.384126 Times computed using real clock time. Number of realloc performed: 0 Unresolved functions not shown : 0 Spontaneous functions not shown : 0 Hidden functions due to -not/-only: 0 Final stack size used: 33 Number of function(s): 10 Flat profile: | local | total | | | | sec. | % | sec. | % | calls |t. sec/call| name |-----------|-----|-----------|-----|----------|-----------|-------- | 0.000048| 0.0| 16.384126|100.0| 1| 16.384126| main | 4.038762| 24.7| 8.078811| 49.3| 4| 2.019703| recurs_1s | 2.677678| 16.3| 5.348654| 32.6| 4| 1.337163| recurs_a | 2.670976| 16.3| 4.679084| 28.6| 4| 1.169771| recurs_b | 4.040041| 24.7| 4.040041| 24.7| 4| 1.010010| s1 | 2.956495| 18.0| 2.956495| 18.0| 1| 2.956495| test | 0.000055| 0.0| 0.000103| 0.0| 32| 0.000003| recurs | 0.000009| 0.0| 0.000013| 0.0| 1| 0.000013| f3 | 0.000004| 0.0| 0.000004| 0.0| 3| 0.000001| f1 | 0.000002| 0.0| 0.000002| 0.0| 1| 0.000002| small MIN/MAX total time list: |indx| MIN | MAX |name |----|-------------|-------------|----- | 0| 16.384126| 16.384126| main | 1| 2.019944| 8.078811| recurs_1s | 2| 1.340897| 5.348654| recurs_a | 3| 0.666023| 4.679084| recurs_b | 4| 1.009985| 1.010051| s1 | 5| 2.956495| 2.956495| test | 6| 0.000002| 0.000103| recurs | 7| 0.000013| 0.000013| f3 | 8| 0.000001| 0.000002| f1 | 9| 0.000002| 0.000002| small Call-graph: 'main' [0] (essai.c:128) spontaneously called. 'recurs_1s' [1] (essai.c:56) called by: [0](essai.c:133), [1](essai.c:61), 'recurs_a' [2] (essai.c:68) called by: [0](essai.c:131), [3](essai.c:94), 'recurs_b' [3] (essai.c:82) called by: [2](essai.c:78), 's1' [4] (essai.c:16) called by: [1](essai.c:58), 'test' [5] (essai.c:121) called by: [0](essai.c:137), 'recurs' [6] (essai.c:48) called by: [0](essai.c:129), [6](essai.c:51), 'f3' [7] (essai.c:40) called by: [0](essai.c:138), 'f1' [8] (essai.c:22) called by: [7](essai.c:41), 'small' [9] (essai.c:113) called by: [0](essai.c:139), V. Internal representation --------------------------- FncCheck uses 'nm' command to extract symbol names from functions addresses. If 'nm' is not accessible, or if the symbol is not in the symbol table, the functions name are replaced by their address in hexadecimal. This can append: - if executable name given to 'fncdump' is wrong (bad name, it have been compiled again after stat. generation...) - if you use optimization options in gcc, and perhaps debug options (-pg...) - if you use constructor in C++, which dont appear in symbol table but are treated as functions by gcc. CHANGES: Since V1.1.3, FncCheck uses 'addr2line' instead of 'nm' (but you can still use 'nm' with '-nm' option). This implies new features such as '-calls-details' and '-func-details'. CHANGES: Since V1.1.4, FncCheck uses 'libbfd' (from GNU binutils) to extract function names from symbol addresses. But you can still use 'addr2line' with '-addr2line' option, or 'nm' using '-nm' option. If 'bfd' (and 'iberty') libraries are not available on your system, you can compile 'fncdump' without 'bfd' using the target 'fncdump_nobfd'. In this case only 'nm' and 'addr2line' (default) approaches remain. VI. Licence ------------ GPL. See COPYING for the GPL licence. See COPYING.LIB if you intend to link the 'libfnccheck.so' library to a proprietary program (which is requested to perform profiling). VII. Contact ------------ Author: Yannick Perret (Hexasoft) EMail: yperret@ligim.univ-lyon1.fr HTTP: http://www710.univ-lyon1.fr/~yperret/profiler.html For bugs report, send mail to 'yperret@ligim.univ-lyon1.fr' VIII. Changes ------------- Thank to: Doolittle, Peter Osterlund, Karl Günter Wünsch, Petter Reinholdtsen, Yotam Medini, for their contribution, bugs report, patches, suggestions... Changes from 1.1.5 to 1.2: * add option '-call-graph' which outputs the profiled program call-graph, using VCG format (a call-graph displayer under UNIX/Linux [and other]). Tested: OK. * adding a doc/ dir. Adding a .texi file with the fnccheck/fncdump documentation in it. Adding a fncdump.info file (generated using fncdump.texi and makeinfo). Adding a doc/html/ dir, with an HTML doc in it (using fncdump.texi and texi2html). * adding '-cycles' option. Displays the detected recursions and cycles (non-direct recursions) in the program. For each, display starting/ending function of the cycle and the total time spend in the cycle. * add "titles" to parts of the 'fncdump''s output (i.e "General information:", "Flat profile:", "Call-graph:"...). * create a 'fncinteract.h' header, with corresponding functions in 'fnccheck' lib. It adds some functions to interact with 'fnccheck' lib during execution. The two main functions are 'fnccheck_stop_profile()' and 'fnccheck_start_profile()' which allow the program to stop or re-start the profile treatments. Useful if you want to profile only a small part of your program. ** Not stable **. Note: by default, main() is always part of the profiled functions (because you always enter main() before doing anything). It is possible to start your program 'as if' 'fnccheck_stop_profile()' was called before by using FNCCHK_SUSPEND variable. Note bis: if you desactivate profile before entering a function, and you re-activate it before leaving from this function, the 'fnccheck' library will see an exit from a never-entering (for it) function. I dont know what can happend in this case (but a priori something bad :o) * remove FNCCHK_PID variable. Now fnccheck creates a 'fnccheck.out' file for processes, instead of it is a child process, in which case a 'fnccheck.out_PID' is generated. It is possible to prevent childs to generate dump file by using FNCCHK_NOCHILD shell variable. * change in the way 'total execution time' is performed. * add '-sum-profile' which allows to add the contents of two profile files into a new profile file (useful to cumulate profiles data). Changes from 1.1.4 to 1.1.5: * add an install target for Makefile (Petter Reinholdtsen) * add new DEBUG flags for tracking bugs :o) * separate some code from 'fnccheck.c' and 'fncdump.c'. Now 'fncdump.c' dont need anymore to be linked with 'fnccheck.o'. * use 'libbfd' to extract functions name, file and line. This is the default behavior. You can still use 'nm' (-nm) or 'addr2line' (-addr2line). If you dont have 'libbfd' and 'libiberty' (from GNU binutils) use 'make fncdump_nobfd' instead of 'make fncdump'. It will generates 'fncdump' with only 'nm' and 'addr2line' approaches. * add '-fullname' option. Make files name (if requested) to be displayed with full path. * correct a bug that make 'main' exited twice for the lib when leaving the profiled program using 'exit' (it was changing the final time for main). * developing a new approach for local time propagation from child functions. It compute real local times instead of transmiting time spend in child functions. It changes nothing for ordinary functions but gives correct local times for recursive (and cross-recursive) functions. * add '-real-maxtime' option. Total execution time (using to compute time perecentages) is computed from displayed list of functions instead of the complete list of functions. * few changes in flat profile display. * starting to create a .info file in 'doc/' directory. Not finished yet. In fact I'm using the 'gprof' info file as a base, but I did something wrong and the .info generated is not correct. Still being updating (will be ready for V1.2). Changes from 1.1.3 to 1.1.4: * removing functions that compute average time per call for the lib in fncdump.c and fnccheck.c. Creating instead a fncaverage.c to perform this. Adding also targets for the Makefiles. This new approach uses REAL calls to the lib (and so generates a fnccheck.out file). * change the -avg option in fncdump in order to call the fncaverage prog instead. * internal: add a hash-table for the 'hx_search_function()'. * change some functions to 'inline' for improvement purpose. * switch to '-O3' optimisation (allows 'inline'). * change 'dump' into 'fncdump' (more specific). * rename fncdump options '-calls+' and '-func+' into resp. '-call-details' and '-func-details'. * change options reading system for 'fncdump' in order to accept several option names for the same option (in particular to let people use old options name (-calls+...) with the new version). * update --help, --details. Add version number to --help. * add print of full version number (including devel sub-part) when starting the lib. * add a shell variable FNCCHK_STOP which desactivate the lib at execution (I use it to compare execution time with and without the lib activated). * trying to put some functions 'inline' in order to accelarate treatments. * correcting an index display bug for 'called by' list. * adding some '\n' missing during display. Changes from 1.1.2 to 1.1.3: * internal: create a real call-tree for functions * -only and -not options * -[r]propagate: allow to propagate -only/-not using the call-tree * new archive organisation: - a src/ dir containing dump and lib sources - a test/ dir containing a test program - lib/ and bin/ dirs - recursive Makefile at root for lib, dump, test. * moving "display" part of fnccheck.c in dump.c * change %g to %f for time display for lisibility * add 'static' for fnccheck functions to prevent names colisions * change 'long long int' to 'long int' for speedup/memory optimisation (and because long int is enough for years...) Changes from 1.1.1 to 1.1.2: * improve parts of the _bad_ english of the README.txt * add some help texts in the error messages * add new options to 'dump' (see dump) * change symbol extraction in order to use 'addr2line' * new dump feature: display file/line for functions (if requested) -> not available with '-nm' option. * correct bad names for C++ functions * display MIN and MAX time for functions (see '-no-minmax') * '--details' gives explanations on output informations. * makefile improvements. default target display possible choice. target 'lib' added, target 'all' added. switch -g added. requiered for FILE:LINE infos. IX. ToDo list -------------- * improve the hash-table in 'fncheck.c'. * improve cycle display. At this time I just display the begin and the end of the cycle. Need to display all members of the cycle. * create a 'configure'. In fact, as my lib requieres very few things, it is not critical. * add better dependences for the Makefile. * improve english of 'README.txt' and 'fncdump.texi' X. The 'fncaverage' program ----------------------------- The 'fncaverage' replace the '-avg' option of 'fncdump' program. It is now a separate executable which perform this job. The prog can accept an option which is the number of iteration to perform (the bigger it is, the more precise the results are, but the more time it takes). In fact, this program executes various kind of functions and compare the execution time with and without the fnccheck lib activated. Note: as a side effect, executing this program generates a 'fnccheck.out' stat file corresponding to the test functions (but their are no valid symbols inside).