1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#!/usr/bin/env python
2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#
3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# Copyright (c) 2013 The Chromium Authors. All rights reserved.
4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# found in the LICENSE file.
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
73551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import collections
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import json
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import optparse
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import os
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import re
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import threading
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import time
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import sys
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)from sets import Set
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)from string import Template
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)sys.path.append(os.path.join(sys.path[0], os.pardir, os.pardir, os.pardir,
203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                             'build','android'))
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)from pylib import android_commands
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)from pylib import constants
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)_ENTRIES = [
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Total', '.* r... '),
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Read-only', '.* r--. '),
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Read-write', '.* rw.. '),
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Executable', '.* ..x. '),
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Anonymous total', '.* ""'),
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Anonymous read-write', '.* rw.. .* ""'),
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Anonymous executable (JIT\'ed code)', '.* ..x. .* ""'),
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('File total', '.* .... .* "/.*"'),
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('File read-write', '.* rw.. .* "/.*"'),
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('File executable', '.* ..x. .* "/.*"'),
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('/dev files', '.* r... .* "/dev/.*"'),
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Dalvik', '.* rw.. .* "/.*dalvik.*"'),
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Dalvik heap', '.* rw.. .* "/.*dalvik-heap.*"'),
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Native heap (malloc)', '.* r... .* ".*malloc.*"'),
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Ashmem', '.* rw.. .* "/dev/ashmem '),
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Native library total', '.* r... .* "/data/app-lib/'),
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Native library read-only', '.* r--. .* "/data/app-lib/'),
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Native library read-write', '.* rw-. .* "/data/app-lib/'),
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ('Native library executable', '.* r.x. .* "/data/app-lib/'),
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)]
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def _CollectMemoryStats(memdump, region_filters):
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  processes = []
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  mem_usage_for_regions = None
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  regexps = {}
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for region_filter in region_filters:
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    regexps[region_filter] = re.compile(region_filter)
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for line in memdump:
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if 'PID=' in line:
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mem_usage_for_regions = {}
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      processes.append(mem_usage_for_regions)
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    matched_regions = Set([])
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for region_filter in region_filters:
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if regexps[region_filter].match(line.rstrip('\r\n')):
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        matched_regions.add(region_filter)
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if not region_filter in mem_usage_for_regions:
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          mem_usage_for_regions[region_filter] = {
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              'private_unevictable': 0,
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              'private': 0,
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              'shared_app': 0.0,
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              'shared_app_unevictable': 0.0,
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              'shared_other_unevictable': 0,
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              'shared_other': 0,
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          }
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for matched_region in matched_regions:
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mem_usage = mem_usage_for_regions[matched_region]
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      for key in mem_usage:
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        for token in line.split(' '):
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          if (key + '=') in token:
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            field = token.split('=')[1]
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            if key != 'shared_app':
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              mem_usage[key] += int(field)
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            else:  # shared_app=[\d:\d,\d:\d...]
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              array = field[1:-1].split(',')
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch              for i in xrange(len(array)):
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                shared_app, shared_app_unevictable = array[i].split(':')
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                mem_usage['shared_app'] += float(shared_app) / (i + 2)
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                mem_usage['shared_app_unevictable'] += \
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    float(shared_app_unevictable) / (i + 2)
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            break
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return processes
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def _ConvertMemoryField(field):
92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return str(field / (1024.0 * 1024))
93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def _DumpCSV(processes_stats):
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  total_map = {}
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  i = 0
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for process in processes_stats:
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    i += 1
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    print (',Process ' + str(i) + ',private,private_unevictable,shared_app,' +
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)           'shared_app_unevictable,shared_other,shared_other_unevictable,')
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    for (k, v) in _ENTRIES:
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if not v in process:
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        print ',' + k + ',0,0,0,0,0,'
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        continue
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if not v in total_map:
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        total_map[v] = {'resident':0, 'unevictable':0}
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      total_map[v]['resident'] += (process[v]['private'] +
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                   process[v]['shared_app'])
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      total_map[v]['unevictable'] += process[v]['private_unevictable'] + \
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          process[v]['shared_app_unevictable']
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      print (
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          ',' + k + ',' +
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          _ConvertMemoryField(process[v]['private']) + ',' +
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          _ConvertMemoryField(process[v]['private_unevictable']) + ',' +
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          _ConvertMemoryField(process[v]['shared_app']) + ',' +
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          _ConvertMemoryField(process[v]['shared_app_unevictable']) + ',' +
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          _ConvertMemoryField(process[v]['shared_other']) + ',' +
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          _ConvertMemoryField(process[v]['shared_other_unevictable']) + ','
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          )
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    print ''
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (k, v) in _ENTRIES:
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if not v in total_map:
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      print ',' + k + ',0,0,'
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      continue
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    print (',' + k + ',' + _ConvertMemoryField(total_map[v]['resident']) + ',' +
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           _ConvertMemoryField(total_map[v]['unevictable']) + ',')
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  print ''
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)def _RunManualGraph(package_name, interval):
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  _AREA_TYPES = ('private', 'private_unevictable', 'shared_app',
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 'shared_app_unevictable', 'shared_other',
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                 'shared_other_unevictable')
1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  all_pids = {}
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  legends = ['Seconds'] + [entry + '_' + area
1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           for entry, _ in _ENTRIES
1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           for area in _AREA_TYPES]
1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  should_quit = threading.Event()
1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  def _GenerateGraph():
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    _HTML_TEMPLATE = """
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)<html>
1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  <head>
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    <script type='text/javascript' src='https://www.google.com/jsapi'></script>
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    <script type='text/javascript'>
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      google.load('visualization', '1', {packages:['corechart', 'table']});
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      google.setOnLoadCallback(createPidSelector);
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      var pids = $JSON_PIDS;
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      var pids_info = $JSON_PIDS_INFO;
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      function drawVisualization(pid) {
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        var data = google.visualization.arrayToDataTable(
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          pids_info[pid]
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        );
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        var charOptions = {
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          title: 'Memory Report (KB) for ' + pid,
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          vAxis: {title: 'Time',  titleTextStyle: {color: 'red'}},
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          isStacked : true
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        };
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        var chart = new google.visualization.BarChart(
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            document.getElementById('chart_div'));
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        chart.draw(data, charOptions);
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        var table = new google.visualization.Table(
1683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            document.getElementById('table_div'));
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        table.draw(data);
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      function createPidSelector() {
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        var pid_selector = document.getElementById('pid_selector');
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        for (pid in pids) {
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          var option = document.createElement('option');
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          option.text = option.value = pids[pid];
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          pid_selector.appendChild(option);
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        }
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        pid_selector.addEventListener('change',
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          function() {
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            drawVisualization(this.selectedOptions[0].value);
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          }
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        );
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        drawVisualization(pids[0]);
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    </script>
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  </head>
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  <body>
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PIDS: <select id='pid_selector'></select>
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    <div id='chart_div' style="width: 1024px; height: 800px;"></div>
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    <div id='table_div' style="width: 1024px; height: 640px;"></div>
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  </body>
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)</html>
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)"""
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    pids = sorted(all_pids.keys())
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    pids_info = dict(zip(pids,
1973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         [ [legends] +
1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           all_pids[p] for p in pids
1993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         ]))
2003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    print Template(_HTML_TEMPLATE).safe_substitute({
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        'JSON_PIDS': json.dumps(pids),
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        'JSON_PIDS_INFO': json.dumps(pids_info)
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    })
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  def _CollectStats(count):
2083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    adb = android_commands.AndroidCommands()
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    pid_list = adb.ExtractPid(package_name)
2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    memdump = adb.RunShellCommand('/data/local/tmp/memdump ' +
2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  ' '.join(pid_list))
2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    process_stats = _CollectMemoryStats(memdump,
2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                        [value for (key, value) in _ENTRIES])
2143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    for (pid, process) in zip(pid_list, process_stats):
2153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      first_pid_entry = True
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      for (k, v) in _ENTRIES:
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        if v not in process:
2183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          continue
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        for area_type in _AREA_TYPES:
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          legend = k + '_' + area_type
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          if pid not in all_pids:
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            all_pids[pid] = []
2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          if first_pid_entry:
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            all_pids[pid].append(['%ds' % (count * interval)] +
2253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 [0] * (len(legends) - 1))
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            first_pid_entry = False
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          mem_kb = process[v][area_type] / 1024
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          all_pids[pid][-1][legends.index(legend)] = mem_kb
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  def _Loop():
2313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    count = 0
2323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    while not should_quit.is_set():
2333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      print >>sys.stderr, 'Collecting ', count
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      _CollectStats(count)
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      count += 1
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      should_quit.wait(interval)
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  t = threading.Thread(target=_Loop)
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  print >>sys.stderr, 'Press enter or CTRL+C to stop'
2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  t.start()
2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  try:
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    _ = raw_input()
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  except KeyboardInterrupt:
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    pass
2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  finally:
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    should_quit.set()
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  t.join()
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  _GenerateGraph()
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def main(argv):
2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  parser = optparse.OptionParser(usage='Usage: %prog [options]',
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                 description=__doc__)
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  parser.add_option('-m',
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    '--manual-graph',
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    action='store_true',
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    help='Manually collect data and generate a graph.')
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  parser.add_option('-p',
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    '--package',
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    default=constants.PACKAGE_INFO['chrome'].package,
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    help='Package name to collect.')
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  parser.add_option('-i',
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    '--interval',
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    default=5,
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    type='int',
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    help='Interval in seconds for manual collections.')
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  options, args = parser.parse_args(argv)
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if options.manual_graph:
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return _RunManualGraph(options.package, options.interval)
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  _DumpCSV(_CollectMemoryStats(sys.stdin, [value for (key, value) in _ENTRIES]))
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)if __name__ == '__main__':
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  main(sys.argv)
279