- add sources.
[platform/framework/web/crosswalk.git] / src / tools / memory_watcher / scripts / memprof.pl
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);