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.
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.
12 # memtrace.pl <logfile>
14 # logfile -- The memwatcher.logXXXX file to summarize.
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 (3300): 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
35 my $location_bytes = 0;
36 my $location_hits = 0;
37 my $location_blame = "";
38 my $location_last = "";
39 my $contains_load_lib = 0;
41 open (LOGFILE
, "$file") or die("could not open $file");
46 if ($line =~ m/([0-9]*) bytes, ([0-9]*) items/) {
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;
55 if (!$contains_load_lib) {
56 $leaks{$location_blame} += $location_bytes;
60 $contains_load_lib = 0;
63 #print("stackframe " . $1 . ", " . $2 . "\n");
67 elsif ($line =~ m/Total Bytes:[ ]*([0-9]*)/) {
70 elsif ($line =~ m/LoadLibrary/) {
71 # skip these, they contain false positives.
72 $contains_load_lib = 1;
75 elsif ($line =~ m/=============/) {
78 elsif ($line =~ m/Untracking untracked/) {
81 elsif ($line =~ m/[ ]*([a-z]:\\[a-z]*\\[a-zA-Z_\\0-9\.]*) /) {
83 if ($filename =~ m/memory_watcher/) {
86 if ($filename =~ m/skmemory_stdlib.cpp/) {
89 if ($filename =~ m/stringimpl.cpp/) {
92 if ($filename =~ m/stringbuffer.h/) {
95 if ($filename =~ m/fastmalloc.h/) {
98 if ($filename =~ m/microsoft visual studio 8/) {
101 if ($filename =~ m/platformsdk_win2008_6_1/) {
104 if ($location_blame eq "") {
105 # use this to blame the line
106 $location_blame = $line;
108 # use this to blame the file.
109 # $location_blame = $filename;
111 #print("blaming $location_blame\n");
114 # print("junk: " . $line . "\n");
115 if (! ($line =~ m/GetModuleFileNameA/) ) {
116 $location_last = $line;
121 # now dump our hash table
123 my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks;
124 for ($i=0; $i<@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};
130 printf("TOTAL: %s\n", comma_print
($sum));
133 # Insert commas into an integer after each three digits for printing.
136 $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g;
140 # ----- Main ------------------------------------------------
142 # Get the command line argument
143 my $filename = shift;
146 process_raw
($filename);