| OLD | NEW |
| 1 #!/usr/bin/perl | 1 #!/usr/bin/perl |
| 2 | 2 |
| 3 # | 3 # |
| 4 # Blame callstacks for each memory allocation. | 4 # Blame callstacks for each memory allocation. |
| 5 # Similar to memprof.pl, will also try to filter out unuseful stacks. | 5 # Similar to memprof.pl, will also try to filter out unuseful stacks. |
| 6 # TODO: better describe how these tools differ. | 6 # TODO: better describe how these tools differ. |
| 7 # | 7 # |
| 8 # Usage: | 8 # Usage: |
| 9 # | 9 # |
| 10 # memtrace.pl <logfile> | 10 # memtrace.pl <logfile> |
| 11 # | 11 # |
| 12 # logfile -- The memwatcher.logXXXX file to summarize. | 12 # logfile -- The memwatcher.logXXXX file to summarize. |
| 13 # | 13 # |
| 14 # | 14 # |
| 15 # | 15 # |
| 16 # Sample output: | 16 # Sample output: |
| 17 # | 17 # |
| 18 # 41975368 77.64% f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.c (163):
malloc | 18 # 41,975,368 77.64% f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.c (163
): malloc |
| 19 # 2097152 3.88% c:\src\chrome1\src\webkit\pending\frameloader.cpp (330
0): WebCore::FrameLoader::committedLoad | 19 # 2,097,152 3.88% c:\src\chrome1\src\webkit\pending\frameloader.cpp (3
300): WebCore::FrameLoader::committedLoad |
| 20 # 1572864 2.91% c:\src\chrome1\src\webkit\port\bridge\v8bridge.cpp (21
4): WebCore::V8Bridge::evaluate | 20 # 1,572,864 2.91% c:\src\chrome1\src\webkit\port\bridge\v8bridge.cpp (
214): WebCore::V8Bridge::evaluate |
| 21 # 1572864 2.91% c:\src\chrome1\src\webkit\glue\webframeloaderclient_im
pl.cc (1071): WebFrameLoaderClient::committedLoad | 21 # 1,572,864 2.91% c:\src\chrome1\src\webkit\glue\webframeloaderclient_
impl.cc (1071): WebFrameLoaderClient::committedLoad |
| 22 # 1572864 2.91% c:\src\chrome1\src\v8\src\ast.h (1181): v8::internal::
Visitor::Visit | 22 # 1,572,864 2.91% c:\src\chrome1\src\v8\src\ast.h (1181): v8::internal
::Visitor::Visit |
| 23 # | 23 # |
| 24 # | 24 # |
| 25 # | 25 # |
| 26 # ******** | 26 |
| 27 # Note: The output is not currently sorted. To make it more legible, | |
| 28 # you will want to sort numerically by the first field: | |
| 29 # $ ./memtrace.pl memwatcher.log3620.txt | sort -n -r | |
| 30 # ******** | |
| 31 # | |
| 32 | 27 |
| 33 sub process_raw($) { | 28 sub process_raw($) { |
| 34 my $file = shift; | 29 my $file = shift; |
| 35 | 30 |
| 36 my %leaks = (); | 31 my %leaks = (); |
| 37 | 32 |
| 38 my $location_bytes = 0; | 33 my $location_bytes = 0; |
| 39 my $location_hits = 0; | 34 my $location_hits = 0; |
| 40 my $location_blame = ""; | 35 my $location_blame = ""; |
| 41 my $location_last = ""; | 36 my $location_last = ""; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 # skip these, they contain false positives. | 69 # skip these, they contain false positives. |
| 75 $contains_load_lib = 1; | 70 $contains_load_lib = 1; |
| 76 next; | 71 next; |
| 77 } | 72 } |
| 78 elsif ($line =~ m/=============/) { | 73 elsif ($line =~ m/=============/) { |
| 79 next; | 74 next; |
| 80 } | 75 } |
| 81 elsif ($line =~ m/Untracking untracked/) { | 76 elsif ($line =~ m/Untracking untracked/) { |
| 82 next; | 77 next; |
| 83 } | 78 } |
| 84 elsif ($line =~ m/[ ]*(c:\\trunk\\[a-zA-Z_\\0-9\.]*) /) { | 79 elsif ($line =~ m/[ ]*([a-z]:\\[a-z]*\\[a-zA-Z_\\0-9\.]*) /) { |
| 85 my $filename = $1; | 80 my $filename = $1; |
| 86 if ($filename =~ m/memory_watcher/) { | 81 if ($filename =~ m/memory_watcher/) { |
| 87 next; | 82 next; |
| 88 } | 83 } |
| 89 if ($filename =~ m/skmemory_stdlib.cpp/) { | 84 if ($filename =~ m/skmemory_stdlib.cpp/) { |
| 90 next; | 85 next; |
| 91 } | 86 } |
| 92 if ($filename =~ m/stringimpl.cpp/) { | 87 if ($filename =~ m/stringimpl.cpp/) { |
| 93 next; | 88 next; |
| 94 } | 89 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 116 } else { | 111 } else { |
| 117 # print("junk: " . $line . "\n"); | 112 # print("junk: " . $line . "\n"); |
| 118 if (! ($line =~ m/GetModuleFileNameA/) ) { | 113 if (! ($line =~ m/GetModuleFileNameA/) ) { |
| 119 $location_last = $line; | 114 $location_last = $line; |
| 120 } | 115 } |
| 121 } | 116 } |
| 122 } | 117 } |
| 123 | 118 |
| 124 # now dump our hash table | 119 # now dump our hash table |
| 125 my $sum = 0; | 120 my $sum = 0; |
| 126 my @keys = keys(%leaks); | 121 my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks; |
| 127 for ($i=0; $i<@keys; $i++) { | 122 for ($i=0; $i<@keys; $i++) { |
| 128 my $key = @keys[$i]; | 123 my $key = @keys[$i]; |
| 129 printf "%8d\t%3.2f%%\t%s\n", $leaks{$key}, (100* $leaks{$key} / $total_bytes
), $key; | 124 if (0 == $total_bytes) { $total_bytes = 1; } |
| 125 printf "%11s\t%3.2f%%\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key}
/ $total_bytes), $key; |
| 130 $sum += $leaks{$key}; | 126 $sum += $leaks{$key}; |
| 131 } | 127 } |
| 132 print("TOTAL: $sum\n"); | 128 printf("TOTAL: %s\n", comma_print($sum)); |
| 133 } | 129 } |
| 134 | 130 |
| 131 # Insert commas into an integer after each three digits for printing. |
| 132 sub comma_print { |
| 133 my $num = "$_[0]"; |
| 134 $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g; |
| 135 return $num; |
| 136 } |
| 135 | 137 |
| 136 # ----- Main ------------------------------------------------ | 138 # ----- Main ------------------------------------------------ |
| 137 | 139 |
| 138 # Get the command line argument | 140 # Get the command line argument |
| 139 my $filename = shift; | 141 my $filename = shift; |
| 140 | 142 |
| 141 # Process the file. | 143 # Process the file. |
| 142 process_raw($filename); | 144 process_raw($filename); |
| OLD | NEW |