| OLD | NEW |
| (Empty) |
| 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 # Blame callstacks for each memory allocation. | |
| 7 # Similar to memprof.pl, will also try to filter out unuseful stacks. | |
| 8 # TODO: better describe how these tools differ. | |
| 9 # | |
| 10 # Usage: | |
| 11 # | |
| 12 # memtrace.pl <logfile> | |
| 13 # | |
| 14 # logfile -- The memwatcher.logXXXX file to summarize. | |
| 15 # | |
| 16 # | |
| 17 # | |
| 18 # Sample output: | |
| 19 # | |
| 20 # 41,975,368 77.64% f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.c (163
): malloc | |
| 21 # 2,097,152 3.88% c:\src\chrome1\src\webkit\pending\frameloader.cpp (3
300): WebCore::FrameLoader::committedLoad | |
| 22 # 1,572,864 2.91% c:\src\chrome1\src\webkit\port\bridge\v8bridge.cpp (
214): WebCore::V8Bridge::evaluate | |
| 23 # 1,572,864 2.91% c:\src\chrome1\src\webkit\glue\webframeloaderclient_
impl.cc (1071): WebFrameLoaderClient::committedLoad | |
| 24 # 1,572,864 2.91% c:\src\chrome1\src\v8\src\ast.h (1181): v8::internal
::Visitor::Visit | |
| 25 # | |
| 26 # | |
| 27 # | |
| 28 | |
| 29 | |
| 30 sub process_raw($) { | |
| 31 my $file = shift; | |
| 32 | |
| 33 my %leaks = (); | |
| 34 | |
| 35 my $location_bytes = 0; | |
| 36 my $location_hits = 0; | |
| 37 my $location_blame = ""; | |
| 38 my $location_last = ""; | |
| 39 my $contains_load_lib = 0; | |
| 40 my $total_bytes = 0; | |
| 41 open (LOGFILE, "$file") or die("could not open $file"); | |
| 42 while(<LOGFILE>) { | |
| 43 my $line = $_; | |
| 44 #print "$line"; | |
| 45 chomp($line); | |
| 46 if ($line =~ m/([0-9]*) bytes, ([0-9]*) allocs/) { | |
| 47 | |
| 48 #print "START\n"; | |
| 49 # Dump "prior" frame here | |
| 50 if ($location_bytes > 0) { | |
| 51 #print("GOTLEAK: $location_bytes ($location_hits) $location_blame\n"); | |
| 52 if ($location_blame eq "") { | |
| 53 $location_blame = $location_last; | |
| 54 } | |
| 55 if (!$contains_load_lib) { | |
| 56 $leaks{$location_blame} += $location_bytes; | |
| 57 } | |
| 58 $location_bytes = 0; | |
| 59 $location_blame = ""; | |
| 60 $contains_load_lib = 0; | |
| 61 } | |
| 62 | |
| 63 #print("stackframe " . $1 . ", " . $2 . "\n"); | |
| 64 $location_hits = $2; | |
| 65 $location_bytes = $1; | |
| 66 } | |
| 67 elsif ($line =~ m/Total Bytes:[ ]*([0-9]*)/) { | |
| 68 $total_bytes += $1; | |
| 69 } | |
| 70 elsif ($line =~ m/LoadLibrary/) { | |
| 71 # skip these, they contain false positives. | |
| 72 $contains_load_lib = 1; | |
| 73 next; | |
| 74 } | |
| 75 elsif ($line =~ m/=============/) { | |
| 76 next; | |
| 77 } | |
| 78 elsif ($line =~ m/Untracking untracked/) { | |
| 79 next; | |
| 80 } | |
| 81 elsif ($line =~ m/[ ]*([a-z]:\\[a-z]*\\[a-zA-Z_\\0-9\.]*) /) { | |
| 82 my $filename = $1; | |
| 83 if ($filename =~ m/memory_watcher/) { | |
| 84 next; | |
| 85 } | |
| 86 if ($filename =~ m/skmemory_stdlib.cpp/) { | |
| 87 next; | |
| 88 } | |
| 89 if ($filename =~ m/stringimpl.cpp/) { | |
| 90 next; | |
| 91 } | |
| 92 if ($filename =~ m/stringbuffer.h/) { | |
| 93 next; | |
| 94 } | |
| 95 if ($filename =~ m/fastmalloc.h/) { | |
| 96 next; | |
| 97 } | |
| 98 if ($filename =~ m/microsoft visual studio 8/) { | |
| 99 next; | |
| 100 } | |
| 101 if ($filename =~ m/platformsdk_win2008_6_1/) { | |
| 102 next; | |
| 103 } | |
| 104 if ($location_blame eq "") { | |
| 105 # use this to blame the line | |
| 106 $location_blame = $line; | |
| 107 | |
| 108 # use this to blame the file. | |
| 109 # $location_blame = $filename; | |
| 110 | |
| 111 #print("blaming $location_blame\n"); | |
| 112 } | |
| 113 } else { | |
| 114 # print("junk: " . $line . "\n"); | |
| 115 if (! ($line =~ m/GetModuleFileNameA/) ) { | |
| 116 $location_last = $line; | |
| 117 } | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 # now dump our hash table | |
| 122 my $sum = 0; | |
| 123 my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks; | |
| 124 for ($i=0; $i<@keys; $i++) { | |
| 125 my $key = @keys[$i]; | |
| 126 if (0 == $total_bytes) { $total_bytes = 1; } | |
| 127 printf "%11s\t%3.2f%%\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key}
/ $total_bytes), $key; | |
| 128 $sum += $leaks{$key}; | |
| 129 } | |
| 130 printf("TOTAL: %s\n", comma_print($sum)); | |
| 131 } | |
| 132 | |
| 133 # Insert commas into an integer after each three digits for printing. | |
| 134 sub comma_print { | |
| 135 my $num = "$_[0]"; | |
| 136 $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g; | |
| 137 return $num; | |
| 138 } | |
| 139 | |
| 140 # ----- Main ------------------------------------------------ | |
| 141 | |
| 142 # Get the command line argument | |
| 143 my $filename = shift; | |
| 144 | |
| 145 # Process the file. | |
| 146 process_raw($filename); | |
| OLD | NEW |