home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / perl / scripts-convex / profiling / profiler.pl < prev    next >
Encoding:
Perl Script  |  1993-07-14  |  6.9 KB  |  303 lines

  1. #!/bin/perl --         -*- Mode: Perl -*- 
  2. # pprof - Perl Profiler
  3. # Copyright (C) 1991 Kresten Krab Thorup (krab@iesd.auc.dk).
  4. # $Id: pprof,v 1.4 1992/03/11 03:49:09 krab Exp krab $
  5. # Author          : Kresten Krab Thorup
  6. # Created On      : Wed Mar 11 02:09:48 1992
  7. # Last Modified By: Kresten Krab Thorup
  8. # Last Modified On: Wed Mar 11 04:49:28 1992
  9. # Update Count    : 114
  10. # HISTORY
  11.  
  12. #                                                                   
  13. # Parse profiler options
  14. #                                                                   
  15.  
  16. die "Usage:\tpprof [-o file] script [args..]\n\tpprof -m  for manual page\n"
  17.     if (@ARGV==0);
  18.  
  19. $out = '&STDERR';
  20. if($ARGV[0] =~ /^-o(\w*)/) {
  21.     shift @ARGV;
  22.     if($1 ne '') {
  23.     $out = $1;
  24.     } else {
  25.     $out = shift @ARGV;
  26.     }
  27.  
  28. #
  29. # '-m' will show the manual page
  30. #
  31.  
  32. if($ARGV[0] =~ /^-m/) {
  33.     while(<DATA>) {
  34.     last if (/__END__/);
  35.     }
  36.     $pager = (defined $ENV{PAGER} ? $ENV{PAGER} : 'more');
  37.     open(MAN,"|nroff -t -man|$pager");
  38.     while(<DATA>) {
  39.     last if (/__END__/);
  40.     print MAN $_;
  41.     }
  42.     close(MAN);
  43.     wait;
  44.     exit(0);
  45.  
  46. #                                                                   
  47. # Create the profiler to be do'ne from the script
  48. #                                                                   
  49.  
  50. $TEMP = '/tmp';
  51.  
  52. mkdir("$TEMP/pdb.$$",0744)
  53.     || die "pprof: cannot create $TEMP/pdb.$$\n";
  54. open(PERLDB,">$TEMP/pdb.$$/perldb.pl") 
  55.     || die "pprof: cannot write $TEMP/pdb.$$/perldb.pl\n";
  56. while(<DATA>) {
  57.     last if (/__END__/);
  58.     print PERLDB $_;
  59. }
  60. close(PERLDB);
  61.  
  62. #                                                                   
  63. # Fix options for perl
  64. #                                                                   
  65.  
  66. $program = $ARGV[0];
  67.  
  68. unshift(@ARGV,'-S') 
  69.     unless(-r $ARGV[0]);
  70.  
  71. unshift(@ARGV,'perl',"-I$TEMP/pdb.$$",'-d');
  72.  
  73. #                                                                   
  74. # Ready, steady...
  75. #                                                                   
  76.  
  77. $SIG{'INT'} = $SIG{'TERM'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'cleanup';
  78.  
  79. if(fork) {
  80.     # this is the parent (original) process
  81.  
  82.     # wait for the program to terminate
  83.     $child = wait;
  84.     die "pprof failed!\n" if ($child == -1);
  85.  
  86.     # remove the profiler
  87.     unlink("$TEMP/pdb.$$/perldb.pl");
  88.     rmdir("$TEMP/pdb.$$");
  89.  
  90.     open(PPROF,"<$ENV{HOME}/pprof.$ENV{HOST}.$child") 
  91.     || die "could not open ~/pprof.$child\n";
  92.  
  93.     while(<PPROF>) {
  94.     ($con,$sub,$u,$s,$cu,$cs) = split(/:/);
  95.  
  96.     $User{$sub} += $u;
  97.     $Sys{$sub} += $s;
  98.     $CUser{$sub} += $cu;
  99.     $CSys{$sub} += $cs;
  100.  
  101.     $User{$con} -= $u;
  102.     $Sys{$con} -= $s;
  103.     $CUser{$con} -= $cu;
  104.     $CSys{$con} -= $cs;
  105.  
  106.     $NumCalls{$sub}++;
  107.     }
  108.  
  109.     close(PROF);
  110.     unlink("$ENV{HOME}/pprof.$ENV{HOST}.$child");
  111.  
  112.     open(OUT,">$out");
  113.  
  114.     print OUT "\nProfile of $program:\n\n";
  115.  
  116.     foreach $sub (sort(keys %NumCalls)) {
  117.     ($user, $sys, $cuser, $csys, $calls)
  118.         = ($User{$sub},
  119.            $Sys{$sub},
  120.            $CUser{$sub},
  121.            $CSys{$sub},
  122.            $NumCalls{$sub});
  123.     next if($sub eq '!');
  124.     write OUT;
  125.     }
  126.  
  127.     print OUT "\n";
  128.  
  129. } else {
  130.     # child process
  131.     exec @ARGV;
  132.     die "exec failed";
  133. }
  134.  
  135. sub cleanup {
  136.     warn "pprof: abnormal exit; cleaning up\n";
  137.     unlink("$ENV{HOME}/pprof.$ENV{HOST}.$child");
  138.     unlink("$TEMP/pdb.$$/perldb.pl");
  139.     rmdir("$TEMP/pdb.$$");
  140.     exit(1);
  141. }
  142.  
  143.  
  144. format OUT_TOP = 
  145. Subroutine               User   System CUser  Csystem     Calls
  146. ----------------------------------------------------------------------
  147. .
  148.  
  149. format OUT =
  150. @<<<<<<<<<<<<<<<<<<<<< @##.## @##.## @##.## @##.##      @####
  151. $sub,                  $user, $sys,  $cuser,$csys,      $calls
  152. .
  153.  
  154. __END__
  155. #
  156. # perldb.pl generating profile information in the file
  157. #           $HOME/pprof.$HOST.$PID
  158. #
  159. # Copyright (C) Kresten Krab Thorup 1992
  160. #
  161. package DB;
  162.  
  163. open(PPROF,">$ENV{HOME}/pprof.$ENV{HOST}.$$");
  164.  
  165. sub DB {
  166.     ($stop,$action) = split(/\0/,$dbline{$line});
  167.     eval "package (caller)[0]; $action;";
  168. }
  169.  
  170. sub sub {
  171.     local($context) = $subname;
  172.     local($subname,$user,$sys,$cuser,$csys) = ($sub,times);
  173.     
  174.     # enter statements
  175.     if (wantarray) {
  176.     @i = &$sub;
  177.     print PPROF 
  178.         $context, ':',
  179.         $subname, ':', 
  180.         (times)[0]-$user, ':',
  181.         (times)[1]-$sys, ':',
  182.         (times)[2]-$cuser, ':',
  183.         (times)[3]-$csys, "\n";
  184.     @i;
  185.     }
  186.     else {
  187.     $i = &$sub;
  188.     print PPROF 
  189.         $context, ':',
  190.         $subname, ':', 
  191.         (times)[0]-$user, ':',
  192.         (times)[1]-$sys, ':',
  193.         (times)[2]-$cuser, ':',
  194.         (times)[3]-$csys, "\n";
  195.     $i;
  196.     }
  197. }
  198.  
  199. $subname = '!';
  200.  
  201. 1;
  202.  
  203. __END__
  204. .TH PPROF 1 "10 March 1992" "$Revision: 1.4 $"
  205. .SH NAME
  206. pprof \- profile perl scripts
  207. .SH SYNOPSIS
  208. .B pprof
  209. [
  210. .B \-o 
  211. .I file
  212. .I perl-script 
  213. .I options... 
  214. ]
  215. .SH DESCRIPTION
  216. .I pprof
  217. runs a perl script (as perl scripts are usually run), but collects 
  218. .I profiling
  219. information as the scripts is running.  The profiling calculated is
  220. the total time a subroutine has consumed, that is, without the time
  221. used in it's own subroutine calls.
  222.  
  223. If 
  224. .B \-o
  225. .I file
  226. is given,  the output is written to 
  227. .I file
  228. instead of STDERR which is default.  Further [ 
  229. .I options... 
  230. ] applied to the perl script is simply passed on to it.
  231.  
  232. .SH OUTPUT
  233. A sample run may look like:
  234.  
  235. host$ pprof cvs uv
  236. .br
  237. .I "...Output from cvs uv "
  238.  
  239. Profile of cvs:
  240. .nf
  241. Subroutine               User  System  CUser  Csystem   Calls
  242. -------------------------------------------------------------
  243. main'CatFile             0.00   0.02   0.00   0.00         1
  244. main'CollectSets         0.12   0.00   0.00   0.00         1
  245. main'EntriesToFiles      0.00   0.03   0.00   0.00         1
  246. main'FindNames           0.05   0.05   0.02   0.17         1
  247. main'NameRepository      0.02   0.03   0.00   0.00         1
  248. main'ReadEntries         0.02   0.00   0.00   0.00         1
  249. main'SetLock             0.00   0.02   0.00   0.00         1
  250. main'VersionAndTime      0.10   0.20   0.00   0.00        17
  251. main'VersionNumber       0.08   0.15   0.00   0.00        17
  252. main'WriteEntries        0.02   0.00   0.00   0.00         1
  253. .fi
  254.  
  255. The table shows the consumed time in seconds for each subroutine, as
  256. well as the entire script.  The entries are:
  257. .TP 8
  258. .BI User
  259. Is the time consumed evaluating user code (actually running perl)
  260. .TP 8
  261. .BI System
  262. Is the time consumed during system calls (mostly input/output operations)
  263. .TP 8
  264. .BI CUser
  265. User time consumed by `childs' of the script, that is, mostly calls to
  266. `system' or things evaluated in back quotes
  267. .TP 8
  268. .BI CSystem
  269. Ditto for system
  270. .TP 8
  271. .BI Calls
  272. is the number of times the given subroutine has been called
  273. .SH FILES
  274. .PD 0
  275. .TP 30
  276. .B $HOME/pprof.$HOST.$PID
  277. profile information stored by the script as is is running
  278. .TP
  279. .B /tmp/pdb.$PID/perldb.pl
  280. the actual profiler (both files are removed before you'll ever see
  281. them) 
  282. .SH SEE ALSO
  283. .BR perl(1)
  284. .SH BUGS
  285. Cannot detect time consumption in the main program (i.e. not
  286. inside some subroutine)   
  287. .SH AUTHOR
  288. Kresten Krab Thorup, Aalborg University (krab@iesd.auc.dk)
  289. ----------------------------------------------------------------------
  290.  
  291. --
  292. What you can't do idaw, maybe you can do imorn'
  293.