1 #!/usr/bin/env python 2 # 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 import re 8 import sys 9 10 from sets import Set 11 12 13 _ENTRIES = [ 14 ('Total', '.* r... .*'), 15 ('Read-only', '.* r--. .*'), 16 ('Read-write', '.* rw.. .*'), 17 ('Executable', '.* ..x. .*'), 18 ('Anonymous total', '.* .... .* .*other=[0-9]+ ($|.*chromium:.*)'), 19 ('Anonymous read-write', '.* rw.. .* .*other=[0-9]+ ($|.*chromium:.*)'), 20 ('Anonymous executable (JIT\'ed code)', '.* ..x. .* shared_other=[0-9]+ $'), 21 ('File total', '.* .... .* /.*'), 22 ('File read-write', '.* rw.. .* /.*'), 23 ('File executable', '.* ..x. .* /.*'), 24 ('chromium mmap', '.* r... .*chromium:.*'), 25 ('chromium TransferBuffer', '.* r... .*chromium:.*CreateTransferBuffer.*'), 26 ('Galaxy Nexus GL driver', '.* r... .*pvrsrvkm.*'), 27 ('Dalvik', '.* rw.. .* /.*dalvik.*'), 28 ('Dalvik heap', '.* rw.. .* /.*dalvik-heap.*'), 29 ('Native heap (jemalloc)', '.* r... .* /.*jemalloc.*'), 30 ('System heap', '.* r... .* \\[heap\\]'), 31 ('Ashmem', '.* rw.. .* /dev/ashmem .*'), 32 ('libchromeview.so total', '.* r... .* /.*libchromeview.so'), 33 ('libchromeview.so read-only', '.* r--. .* /.*libchromeview.so'), 34 ('libchromeview.so read-write', '.* rw-. .* /.*libchromeview.so'), 35 ('libchromeview.so executable', '.* r.x. .* /.*libchromeview.so'), 36 ] 37 38 39 def _CollectMemoryStats(memdump, region_filters): 40 processes = [] 41 mem_usage_for_regions = None 42 regexps = {} 43 for region_filter in region_filters: 44 regexps[region_filter] = re.compile(region_filter) 45 for line in memdump: 46 if 'PID=' in line: 47 mem_usage_for_regions = {} 48 processes.append(mem_usage_for_regions) 49 continue 50 matched_regions = Set([]) 51 for region_filter in region_filters: 52 if regexps[region_filter].match(line.rstrip('\r\n')): 53 matched_regions.add(region_filter) 54 if not region_filter in mem_usage_for_regions: 55 mem_usage_for_regions[region_filter] = { 56 'private_unevictable': 0, 57 'private': 0, 58 'shared_app': 0.0, 59 'shared_other_unevictable': 0, 60 'shared_other': 0, 61 } 62 for matched_region in matched_regions: 63 mem_usage = mem_usage_for_regions[matched_region] 64 for key in mem_usage: 65 for token in line.split(' '): 66 if (key + '=') in token: 67 field = token.split('=')[1] 68 if key != 'shared_app': 69 mem_usage[key] += int(field) 70 else: # shared_app=[\d,\d...] 71 array = eval(field) 72 for i in xrange(len(array)): 73 mem_usage[key] += float(array[i]) / (i + 2) 74 break 75 return processes 76 77 78 def _ConvertMemoryField(field): 79 return str(field / (1024.0 * 1024)) 80 81 82 def _DumpCSV(processes_stats): 83 total_map = {} 84 i = 0 85 for process in processes_stats: 86 i += 1 87 print (',Process ' + str(i) + ',private,private_unevictable,shared_app,' + 88 'shared_other,shared_other_unevictable,') 89 for (k, v) in _ENTRIES: 90 if not v in process: 91 print ',' + k + ',0,0,0,0,' 92 continue 93 if not v in total_map: 94 total_map[v] = {'resident':0, 'unevictable':0} 95 total_map[v]['resident'] += (process[v]['private'] + 96 process[v]['shared_app']) 97 total_map[v]['unevictable'] += process[v]['private_unevictable'] 98 print ( 99 ',' + k + ',' + 100 _ConvertMemoryField(process[v]['private']) + ',' + 101 _ConvertMemoryField(process[v]['private_unevictable']) + ',' + 102 _ConvertMemoryField(process[v]['shared_app']) + ',' + 103 _ConvertMemoryField(process[v]['shared_other']) + ',' + 104 _ConvertMemoryField(process[v]['shared_other_unevictable']) + ',' 105 ) 106 print '' 107 108 for (k, v) in _ENTRIES: 109 if not v in total_map: 110 print ',' + k + ',0,0,' 111 continue 112 print (',' + k + ',' + _ConvertMemoryField(total_map[v]['resident']) + ',' + 113 _ConvertMemoryField(total_map[v]['unevictable']) + ',') 114 print '' 115 116 117 def main(argv): 118 _DumpCSV(_CollectMemoryStats(sys.stdin, [value for (key, value) in _ENTRIES])) 119 120 121 if __name__ == '__main__': 122 main(sys.argv) 123