Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/perl
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 #
      6 # Read a memtrace logfile from stdin and group memory allocations by logical
      7 # code component. The code component is guessed from the callstack, and
      8 # is something like {v8, sqlite, disk cache, skia, etc..}
      9 #
     10 # Usage:
     11 #
     12 #   summary.pl
     13 #
     14 #      [STDIN] -- The memwatcher.logXXXX file to summarize.
     15 #
     16 
     17 sub process_stdin() {
     18   my %leaks = ();
     19   my $total_bytes = 0;
     20 
     21   while(<STDIN>) {
     22     my $line = $_;
     23     chomp($line);
     24     my $bytes, $loc;
     25     ($bytes, $loc) = ($line =~ m/[ \t]*([0-9]*)[ \t]*[0-9\.%]*[ \t]*(.*)/);
     26     chomp($loc);
     27     while(<STDIN>) {
     28 	my $cont = $_;
     29         chomp($cont);
     30         last if $cont =~ m/=====/;
     31 	$loc .= "\n" . $cont;
     32     }
     33     my $location_blame = "";
     34 
     35 #    print "Found: $bytes, $loc\n";
     36     
     37     if ($loc =~ m/v8::internal::Snapshot::Deserialize/) {
     38       $location_blame = "v8 Snapshot Deserialize";
     39     } elsif ($loc =~ m/RenderStyle::create/) {
     40       $location_blame = "RenderStyle::create";
     41     } elsif ($loc =~ m/v8::internal::OldSpace::SlowAllocateRaw/) {
     42       $location_blame = "v8 OldSpace";
     43     } elsif ($loc =~ m/sqlite/) {
     44       $location_blame = "sqlite";
     45     } elsif ($loc =~ m/ TransportDIB::Map/) {
     46       $location_blame = "Shared Memory Backing Store";
     47     } elsif ($loc =~ m/imagedecoder/) {
     48       $location_blame = "img decoder";
     49     } elsif ($loc =~ m/SkBitmap/) {
     50       $location_blame = "skia";
     51     } elsif ($loc =~ m/disk_cache/) {
     52       $location_blame = "disk cache";
     53     } elsif ($loc =~ m/skia/) {
     54       $location_blame = "skia";
     55     } elsif ($loc =~ m/:WSA/) {
     56       $location_blame = "net";
     57     } elsif ($loc =~ m/dns/) {
     58       $location_blame = "net";
     59     } elsif ($loc =~ m/trunk\\net/) {
     60       $location_blame = "net";
     61     } elsif ($loc =~ m/WinHttp/) {
     62       $location_blame = "WinHttp";
     63     } elsif ($loc =~ m/:I_Crypt/) {
     64       $location_blame = "WinHttpSSL";
     65     } elsif ($loc =~ m/CryptGetTls/) {
     66       $location_blame = "WinHttpSSL";
     67     } elsif ($loc =~ m/WinVerifyTrust/) {
     68       $location_blame = "WinHttpSSL";
     69     } elsif ($loc =~ m/Cert/) {
     70       $location_blame = "WinHttpSSL";
     71     } elsif ($loc =~ m/plugin/) {
     72       $location_blame = "plugin";
     73     } elsif ($loc =~ m/NP_/) {
     74       $location_blame = "plugin";
     75     } elsif ($loc =~ m/hunspell/) {
     76       $location_blame = "hunspell";
     77     } elsif ($loc =~ m/TextCodec/) {
     78       $location_blame = "fonts";
     79     } elsif ($loc =~ m/glyph/) {
     80       $location_blame = "fonts";
     81     } elsif ($loc =~ m/cssparser/) {
     82       $location_blame = "webkit css";
     83     } elsif ($loc =~ m/::CSS/) {
     84       $location_blame = "webkit css";
     85     } elsif ($loc =~ m/Arena/) {
     86       $location_blame = "webkit arenas";
     87     } elsif ($loc =~ m/WebCore::.*ResourceLoader::addData/) {
     88       $location_blame = "WebCore *ResourceLoader addData";
     89     } elsif ($loc =~ m/OnUpdateVisitedLinks/) {
     90       $location_blame = "OnUpdateVisitedLinks";
     91     } elsif ($loc =~ m/IPC/) {
     92       $location_blame = "ipc";
     93     } elsif ($loc =~ m/trunk\\chrome\\browser/) {
     94       $location_blame = "browser";
     95     } elsif ($loc =~ m/trunk\\chrome\\renderer/) {
     96       $location_blame = "renderer";
     97     } elsif ($loc =~ m/webcore\\html/) {
     98       $location_blame = "webkit webcore html";
     99     } elsif ($loc =~ m/webkit.*string/) {
    100       $location_blame = "webkit strings";
    101     } elsif ($loc =~ m/htmltokenizer/) {
    102       $location_blame = "webkit HTMLTokenizer";
    103     } elsif ($loc =~ m/javascriptcore/) {
    104       $location_blame = "webkit javascriptcore";
    105     } elsif ($loc =~ m/webkit/) {
    106       $location_blame = "webkit other";
    107     } elsif ($loc =~ m/safe_browsing/) {
    108       $location_blame = "safe_browsing";
    109     } elsif ($loc =~ m/VisitedLinkMaster/) {
    110       $location_blame = "VisitedLinkMaster";
    111     } elsif ($loc =~ m/NewDOMUI/) {
    112       $location_blame = "NewDOMUI";
    113     } elsif ($loc =~ m/RegistryControlledDomainService/) {
    114       $location_blame = "RegistryControlledDomainService";
    115     } elsif ($loc =~ m/URLRequestChromeJob::DataAvailable/) {
    116       $location_blame = "URLRequestChromeJob DataAvailable";
    117     } elsif ($loc =~ m/history_publisher/) {
    118       $location_blame = "history publisher";
    119     } else {
    120       $location_blame = "unknown";
    121     }
    122 
    123     # Surface large outliers in an "interesting" group.
    124     my $interesting_group = "unknown";
    125     my $interesting_size = 10000000;  # Make this smaller as needed.
    126     # TODO(jar): Add this as a pair of shell arguments.
    127     if ($bytes > $interesting_size && $location_blame eq $interesting_group) {
    128       # Create a special group for the exact stack that contributed so much.
    129       $location_blame = $loc;
    130     }
    131 
    132     $total_bytes += $bytes;
    133     $leaks{$location_blame} += $bytes;
    134   }
    135 
    136   # now dump our hash table
    137   my $sum = 0;
    138   my @keys = sort { $leaks{$b} <=> $leaks{$a}  }keys %leaks;
    139   for ($i=0; $i<@keys; $i++) {
    140     my $key = @keys[$i];
    141     printf "%11s\t(%3.2f%%)\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key} / $total_bytes), $key;
    142     $sum += $leaks{$key};
    143   }
    144   printf("TOTAL: %s\n", comma_print($sum));
    145 }
    146 
    147 # Insert commas into an integer after each three digits for printing.
    148 sub comma_print {
    149     my $num = "$_[0]";
    150     $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g;
    151     return $num;
    152 }
    153 
    154 # ----- Main ------------------------------------------------
    155 
    156 process_stdin();
    157