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