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 |