1cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci#!/usr/bin/env python
2cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci#
3cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# Copyright (C) 2013 The Android Open Source Project
4cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci#
5cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# Licensed under the Apache License, Version 2.0 (the "License");
6cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# you may not use this file except in compliance with the License.
7cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# You may obtain a copy of the License at
8cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci#
9cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci#      http://www.apache.org/licenses/LICENSE-2.0
10cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci#
11cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# Unless required by applicable law or agreed to in writing, software
12cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# distributed under the License is distributed on an "AS IS" BASIS,
13cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# See the License for the specific language governing permissions and
15cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci# limitations under the License.
16cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
17cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci"""WebView postprocessor for the go/memdump tool.
18cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
19cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano TucciProcesses the output of memdump (see go/memdump) aggregating memory usage
20cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucciinformation for WebView analysis (both classic and chromium).
21cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
22cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano TucciUsage: adb shell /path/to/target/memdump <target-PID> | ./memreport.py > out.csv
23cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci"""
24cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
25cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
26cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucciimport os
27cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucciimport re
28cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucciimport sys
29cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
30cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tuccifrom sets import Set
31cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
32cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
33cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci_ENTRIES = [
34cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('Total', '.* r... .*'),
35cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Read-only', '.* r--. .*'),
36cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Read-write', '.* rw.. .*'),
37cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  Read-write (no x)', '.* rw-. .*'),
38cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Executable', '.* ..x. .*'),
39cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('Anonymous total', '.* .... .* .*shared_other=[0-9]+ ($|.*dlmalloc.*)'),
40cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Anonymous executable (JIT)', '.* ..x. .* shared_other=[0-9]+ ($|.*dlmalloc.*)'),
41cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Anonymous read-write', '.* rw.. .* .*shared_other=[0-9]+ ($|.*dlmalloc.*)'),
42cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  Native heap (dlmalloc)', '.* r... .* /.*dlmalloc.*'),
43cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('File total', '.* .... .* /((?!dev/ashmem/dlmalloc).*)'),
44cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' File executable', '.* ..x. .* /((?!dev/ashmem/dlmalloc).*)'),
45cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' File read-write', '.* rw.. .* /((?!dev/ashmem/dlmalloc).*)'),
46cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Dalvik', '.* rw.. .* /.*dalvik.*'),
47cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  Dalvik heap', '.* rw.. .* /.*dalvik-heap.*'),
48cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Ashmem', '.* rw.. .* /dev/ashmem .*'),
49cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' libwebcore.so total', '.* r... .* /.*libwebcore.so'),
50cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  libwebcore.so read-only', '.* r--. .* /.*libwebcore.so'),
51cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  libwebcore.so read-write', '.* rw-. .* /.*libwebcore.so'),
52cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  libwebcore.so executable', '.* r.x. .* /.*libwebcore.so'),
53cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' libwebviewchromium.so total', '.* r... .* /.*libwebviewchromium.so'),
54cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  libwebviewchromium.so read-only', '.* r--. .* /.*libwebviewchromium.so'),
55cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  libwebviewchromium.so read-write', '.* rw-. .* /.*libwebviewchromium.so'),
56cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  libwebviewchromium.so executable', '.* r.x. .* /.*libwebviewchromium.so'),
57cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' Driver mappings', '.* .... .* /dev/\w+$'),
58cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('  /dev/maliN total', '.* .... .* /dev/mali.*'),
59cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ('OTHER (non file non anon)', '.* .... .*shared_other=[0-9]+ [^/]+'),
60cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    (' DMA buffers', '.* .... .*shared_other=[0-9]+ .*dmabuf.*'),
61cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    ]
62cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
63cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
64cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tuccidef _CollectMemoryStats(memdump, region_filters):
65cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  processes = []
66cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  mem_usage_for_regions = None
67cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  regexps = {}
68cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  for region_filter in region_filters:
69cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    regexps[region_filter] = re.compile(region_filter)
70cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  for line in memdump:
71cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    if 'PID=' in line:
72cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      mem_usage_for_regions = {}
73cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      processes.append(mem_usage_for_regions)
74cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      continue
75cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    matched_regions = Set([])
76cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    for region_filter in region_filters:
77cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      if regexps[region_filter].match(line.rstrip('\r\n')):
78cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci        matched_regions.add(region_filter)
79cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci        if not region_filter in mem_usage_for_regions:
80cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          mem_usage_for_regions[region_filter] = {
81cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              'private_unevictable': 0,
82cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              'private': 0,
83cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              'shared_app': 0.0,
84cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              'shared_other_unevictable': 0,
85cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              'shared_other': 0,
86cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          }
87cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    for matched_region in matched_regions:
88cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      mem_usage = mem_usage_for_regions[matched_region]
89cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      for key in mem_usage:
90cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci        for token in line.split(' '):
91cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          if (key+'=') in token:
92cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci            field = token.split('=')[1]
93cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci            if key != 'shared_app':
94cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              mem_usage[key] += int(field)
95cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci            else:  # shared_app=[\d,\d...]
96cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              array = eval(field)
97cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci              for i in xrange(len(array)):
98cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci                mem_usage[key] += float(array[i]) / (i + 2)
99cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci            break
100cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  return processes
101cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
102cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
103cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tuccidef _ConvertMemoryField(field):
104cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  return str(field / (1024))
105cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
106cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
107cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tuccidef _DumpCSV(processes_stats):
108cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  total_map = {}
109cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  i = 0
110cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  for process in processes_stats:
111cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    i += 1
112cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    print ',private,private_unevictable,shared_other,shared_other_unevictable,'
113cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci    for (k, v) in _ENTRIES:
114cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      header_column = k + ',' if 'NOHEADER' not in os.environ else ','
115cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      if not v in process:
116cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci        print header_column + '0,0,0,0,'
117cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci        continue
118cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      if not v in total_map:
119cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci        total_map[v] = 0
120cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      total_map[v] += process[v]['private'] + process[v]['shared_app']
121cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci      print (
122cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          header_column +
123cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          _ConvertMemoryField(process[v]['private']) + ',' +
124cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          _ConvertMemoryField(process[v]['private_unevictable']) + ',' +
125cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          _ConvertMemoryField(process[v]['shared_other']) + ',' +
126cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          _ConvertMemoryField(process[v]['shared_other_unevictable']) + ','
127cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci          )
128cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
129cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
130cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tuccidef main(argv):
131cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  _DumpCSV(_CollectMemoryStats(sys.stdin, [value for (key, value) in _ENTRIES]))
132cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
133cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci
134cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucciif __name__ == '__main__':
135cea1472db7958488e2fe7822250f4d1eba6cfd2cPrimiano Tucci  main(sys.argv)
136