Home | History | Annotate | Download | only in memdump
      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