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 # Given a memwatcher logfile, group memory allocations by callstack. | |
7 # | |
8 # Usage: | |
9 # | |
10 # memprof.pl <logfile> | |
11 # | |
12 # logfile -- The memwatcher.logXXXX file to summarize. | |
13 # | |
14 # | |
15 # | |
16 # Sample output: | |
17 # | |
18 # 54,061,617 100.00% AllocationStack::AllocationStack | |
19 # 41,975,368 77.64% malloc | |
20 # 11,886,592 21.99% VirtualAlloc | |
21 # 7,168,000 13.26% v8::internal::OS::Allocate | |
22 # 7,168,000 13.26% v8::internal::MemoryAllocator::AllocateRawMemory | |
23 # 5,976,184 11.05% WebCore::V8Bridge::evaluate | |
24 # 5,767,168 10.67% v8::internal::MemoryAllocator::AllocatePages | |
25 # 5,451,776 10.08% WebCore::V8Proxy::initContextIfNeeded | |
26 # .... | |
27 # | |
28 # | |
29 # | |
30 # ******** | |
31 # Note: The output is currently sorted by decreasing size. | |
32 # ******** | |
33 # | |
34 | |
35 sub process_raw($$) { | |
36 my $file = shift; | |
37 my $filter = shift; | |
38 | |
39 my %leaks = (); | |
40 my %stackframes = (); | |
41 | |
42 my $blamed = 0; | |
43 my $bytes = 0; | |
44 my $hits = 0; | |
45 open (LOGFILE, "$file") or die("could not open $file"); | |
46 while(<LOGFILE>) { | |
47 my $line = $_; | |
48 #print "$line"; | |
49 chomp($line); | |
50 if ($line =~ m/([0-9]*) bytes, ([0-9]*) allocs/) { | |
51 | |
52 # If we didn't find any frames to account this to, log that. | |
53 if ($blamed == 0) { | |
54 $leaks{"UNACCOUNTED"} += $bytes; | |
55 } | |
56 | |
57 #print "START\n"; | |
58 #print("stackframe " . $1 . ", " . $2 . "\n"); | |
59 $hits = $2; | |
60 $bytes = $1; | |
61 %stackframes = (); # we have a new frame, clear the list. | |
62 $blamed = 0; # we haven't blamed anyone yet | |
63 } | |
64 elsif ($line =~ m/Total Bytes:[ ]*([0-9]*)/) { | |
65 $total_bytes += $1; | |
66 } | |
67 elsif ($line =~ m/=============/) { | |
68 next; | |
69 } | |
70 elsif ($line =~ m/[ ]*([\-a-zA-Z_\\0-9\.]*) \(([0-9]*)\):[ ]*([<>_a-zA-Z_0-9
:]*)/) { | |
71 # print("junk: " . $line . "\n"); | |
72 # print("file: $1\n"); | |
73 # print("line: $2\n"); | |
74 # print("function: $3\n"); | |
75 # | |
76 | |
77 # blame the function | |
78 my $pig = $3; | |
79 # my $pig = $1; | |
80 | |
81 # only add the memory if this function is not yet on our callstack | |
82 if (!exists $stackframes{$pig}) { | |
83 $leaks{$pig} += $bytes; | |
84 } | |
85 | |
86 $stackframes{$pig}++; | |
87 $blamed++; | |
88 } | |
89 } | |
90 | |
91 # now dump our hash table | |
92 my $sum = 0; | |
93 my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks; | |
94 for ($i=0; $i<@keys; $i++) { | |
95 my $key = @keys[$i]; | |
96 printf "%11s\t%3.2f%%\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key}
/ $total_bytes), $key; | |
97 $sum += $leaks{$key}; | |
98 } | |
99 printf("TOTAL: %s\n", comma_print($sum)); | |
100 } | |
101 | |
102 # Insert commas into an integer after each three digits for printing. | |
103 sub comma_print { | |
104 my $num = "$_[0]"; | |
105 $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g; | |
106 return $num; | |
107 } | |
108 | |
109 # ----- Main ------------------------------------------------ | |
110 | |
111 # Get the command line argument | |
112 my $filename = shift; | |
113 my $filter = shift; | |
114 | |
115 # Process the file. | |
116 process_raw($filename, $filter); | |
OLD | NEW |