Changeset 2d9e75d for memlog_analyze


Ignore:
Timestamp:
07/22/15 14:18:06 (9 years ago)
Author:
Hal Finkel <hfinkel@…>
Branches:
master
Children:
96927c5
Parents:
09f3093 (diff), 3c9fc94 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Hal Finkel <hfinkel@…> (07/22/15 14:18:06)
git-committer:
Hal Finkel <hfinkel@…> (07/22/15 14:18:06)
Message:

Merge branch 'master' of git.mcs.anl.gov:memlog

File:
1 moved

Legend:

Unmodified
Added
Removed
  • memlog_analyze

    r09f3093 r2d9e75d  
    4242use strict; 
    4343use File::Basename; 
     44use File::Path qw(make_path); 
     45use Getopt::Long; 
     46 
     47my $find_leaks = 0; 
     48my $print_raw_proc_name = 0; 
     49my $quiet = 0; 
     50my $help = 0; 
     51 
     52sub print_usage($) { 
     53  my $ec = $_[0]; 
     54  my $usage = <<EOM; 
     55Usage: $0 [options] <memlog file or glob> [<output directory>] 
     56  options: 
     57    --leaks 
     58      Provide information on leaks instead of peak usage 
     59    --print-symbol-names 
     60      Include symbol names and offsets in the output 
     61    --quiet or -q 
     62      Don't print status messages while running 
     63EOM 
     64 
     65  print $usage; 
     66  exit($ec); 
     67} 
     68 
     69GetOptions("help|h|?" => \$help, 
     70           "leaks" => \$find_leaks, 
     71           "print-symbol-names" => \$print_raw_proc_name, 
     72           "quiet|q" => \$quiet) 
     73  or print_usage(1); 
     74 
     75if ($help) { 
     76  print_usage(0); 
     77} 
     78 
     79if (scalar(@ARGV) > 2) { 
     80  print_usage(2); 
     81} 
    4482 
    4583my $memlog_fn = $ARGV[0]; 
    4684my $out_dir = $ARGV[1] || '.'; 
    4785 
    48 my $print_raw_proc_name = 0; 
     86make_path($out_dir); 
    4987 
    5088if (! -f $memlog_fn) { 
    51   print "Usage: $0 <memlog file> [<output directory>]\n"; 
    52   exit 1; 
    53 } 
     89  my @pot_fns = glob($memlog_fn); 
     90  if (scalar(@pot_fns)) { 
     91    if (!$quiet) { 
     92      print "Searching all files matching '$memlog_fn'\n"; 
     93    } 
     94 
     95    my $pot_max_rss = 0; 
     96    my $pos_max_rss_fn; 
     97    foreach my $pot_fn (@pot_fns) { 
     98      my $last_line = `tail -n 1 '$pot_fn'`; 
     99      chomp($last_line); 
     100 
     101      my @parts = split(/\t/, $last_line); 
     102 
     103      my $op = shift(@parts); 
     104      my $state = shift(@parts); 
     105 
     106      my ($time, $then_max_rss, $tid, $then_arena, $then_mmap) = 
     107        split(/\s+/, $state); 
     108      if ($pot_max_rss < $then_max_rss) { 
     109        $pot_max_rss = $then_max_rss; 
     110        $pos_max_rss_fn = $pot_fn; 
     111      } 
     112    } 
     113 
     114    if (defined $pos_max_rss_fn) { 
     115      $memlog_fn = $pos_max_rss_fn; 
     116      goto have_memlog_fn; 
     117    } 
     118  } 
     119 
     120  print_usage(1); 
     121} 
     122have_memlog_fn: 
    54123 
    55124# The version of addr2line and friends that you use can make a big difference, 
     
    66135# The first step is to determine the high-water mark. 
    67136my $max_rss = 0; 
     137my $arena = 0; 
     138my $mmap = 0; 
    68139foreach my $line (<MEMLOG>) { 
    69140  chomp($line); 
     
    73144  my $state = shift(@parts); 
    74145 
    75   my ($time, $then_max_rss, $tid) = split(/\s+/, $state); 
     146  my ($time, $then_max_rss, $tid, $then_arena, $then_mmap) = 
     147    split(/\s+/, $state); 
    76148  if ($max_rss < $then_max_rss) { 
    77149    $max_rss = $then_max_rss; 
     150    $arena = $then_arena; 
     151    $mmap = $then_mmap; 
    78152  } 
    79153} 
     
    83157# Scan the log for malloc/free pairings. We're interested only in active 
    84158# allocations at the time when the rss reaches the final maxrss. 
    85 my $max_rss_time = 0; 
     159# If we're finding leaks, then go to the very end. 
     160my $active_alloc_time = 0; 
    86161my %malloc_lines; 
    87162foreach my $line (<MEMLOG>) { 
     
    102177  } 
    103178 
    104   # If we've reached the max rss, we've seen all we need to see. 
    105   my ($time, $then_max_rss, $tid) = split(/\s+/, $state); 
    106   $max_rss_time = $time; 
    107   if ($then_max_rss == $max_rss) { 
    108     last; 
     179  my ($time, $then_max_rss, $tid, $then_arena, $then_mmap) = 
     180    split(/\s+/, $state); 
     181  $active_alloc_time = $time; 
     182 
     183  if (!$find_leaks) { 
     184    # If we've reached the max rss, we've seen all we need to see. 
     185    if ($then_max_rss == $max_rss) { 
     186      last; 
     187    } 
    109188  } 
    110189} 
     
    114193# Convert maxrss, currently in KB, to bytes. 
    115194$max_rss *= 1024; 
     195if (defined $arena) { 
     196  $arena *= 1024; 
     197} 
     198if (defined $mmap) { 
     199  $mmap *= 1024; 
     200} 
    116201 
    117202my $total_size = 0; 
     
    130215 
    131216  my ($size, $ptr) = ($op =~ /^M: (\d+) 0x(\w+)/); 
    132   my ($time, $then_max_rss, $tid) = split(/\s+/, $state); 
     217  my ($time, $then_max_rss, $tid, $then_arena, $then_mmap) = 
     218    split(/\s+/, $state); 
    133219 
    134220  $total_size += $size; 
     
    192278my $pdf_fn = "$out_dir/" . basename($memlog_fn) . ".pdf"; 
    193279 
     280if (!$quiet) { 
     281  print "Creating $txt_fn\n"; 
     282} 
     283 
    194284open(TXT, ">$txt_fn") || die "Can't open $txt_fn: $!"; 
     285 
     286if (!$quiet) { 
     287  print "Creating $dot_fn\n"; 
     288} 
     289 
    195290open(DOT, ">$dot_fn") || die "Can't open $dot_fn: $!"; 
    196291 
     
    208303} 
    209304 
     305sub format_bytes_or_unk($) { 
     306  my $b = $_[0]; 
     307  return defined($b) ? format_bytes($b) : "(unknown)"; 
     308} 
     309 
    210310print DOT ("digraph \"memlog\" {\n"); 
    211311print DOT ("size=\"8,11\";\n"); 
    212312print DOT ("node [width=0.375,height=0.25];\n"); 
    213313 
    214 printf DOT ("Legend [shape=box, fontsize=100, shape=oval," . 
    215             "label=\"Total: %s active at maxrss = %s after %s s\"];\n", 
    216             format_bytes($total_size), format_bytes($max_rss), $max_rss_time); 
    217  
    218 printf TXT ("memlog: Total: %s active at maxrss = %s after %s s\n\n", 
    219             format_bytes($total_size), format_bytes($max_rss), $max_rss_time); 
     314my $find_type = $find_leaks ? " (leaks)" : ""; 
     315print DOT "subgraph cluster_key {\n"; 
     316print DOT "\trank=min;\n"; 
     317print DOT "\tlabel=\"memlog\";\n"; 
     318print DOT "\tfontsize=100;\n"; 
     319print DOT "\trankdir=UR;\n"; 
     320printf DOT ("Legend [shape=box, fontsize=100, shape=plaintext," . 
     321            "label=\"Total: %s active$find_type at maxrss = %s after %s s\\narena: %s\\nmmap: %s\"];\n", 
     322            format_bytes($total_size), format_bytes($max_rss), 
     323            $active_alloc_time, format_bytes_or_unk($arena), 
     324            format_bytes_or_unk($mmap)); 
     325print DOT "}\n"; 
     326 
     327printf TXT ("memlog: Total: %s active$find_type at maxrss = %s after %s s\n\tarena: %s\tmmap: %s\n\n", 
     328            format_bytes($total_size), format_bytes($max_rss), 
     329            $active_alloc_time, format_bytes_or_unk($arena), 
     330            format_bytes_or_unk($mmap)); 
    220331 
    221332my %cached_names; 
     
    277388    $ret .= $func . '\n'; 
    278389 
    279     if ($loc !~ /^\?/) { 
     390    if ($loc !~ /^[:?]/) { 
    280391      $ret .= $loc . '\n'; 
    281392    } 
     
    395506close(DOT); 
    396507 
     508if (!$quiet) { 
     509  print "Creating $ps_fn\n"; 
     510} 
     511 
    397512system("dot -Tps2 < '$dot_fn' > '$ps_fn'"); 
     513 
     514if (!$quiet) { 
     515  print "Creating $pdf_fn\n"; 
     516} 
     517 
    398518system("ps2pdf '$ps_fn' '$pdf_fn'"); 
    399519 
Note: See TracChangeset for help on using the changeset viewer.