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 |