Skip to content

Commit

Permalink
Further enhancements to command_line frontend to memory_inspector
Browse files Browse the repository at this point in the history
Print memory maps for a process
Print consolidated memory map data for a process

BUG=340294
NOTRY=true

Review URL: https://codereview.chromium.org/240023003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@265655 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
paulwhitton@google.com committed Apr 23, 2014
1 parent 27d0c1c commit 9f0c7f5
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 75 deletions.
168 changes: 94 additions & 74 deletions tools/memory_inspector/memory_inspector/frontends/command_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@

"""Command line frontend for Memory Inspector"""

import json
import memory_inspector
import optparse
import os
import time

from memory_inspector.classification import mmap_classifier
from memory_inspector.core import backends
from memory_inspector.data import serialization


def main(argv):
usage = '%prog [options] devices | ps | stats'
def main():
COMMANDS = ['devices', 'ps', 'stats', 'mmaps', 'classified_mmaps']
usage = ('%prog [options] ' + ' | '.join(COMMANDS))
parser = optparse.OptionParser(usage=usage)
parser.add_option('-b', '--backend', help='Backend name '
'(e.g., Android)', type='string', default='Android')
Expand All @@ -22,13 +27,18 @@ def main(argv):
type='int')
parser.add_option('-m', '--filter_process_name', help='Process '
'name to match', type='string')
parser.add_option('-r', '--mmap_rule',
help='mmap rule', type='string',
default=
'classification_rules/default/mmap-android.py')
(options, args) = parser.parse_args()

memory_inspector.RegisterAllBackends()

if not args:
if not args or args[0] not in COMMANDS:
parser.print_help()
return -1

if args[0] == 'devices':
_ListDevices(options.backend)
return 0
Expand All @@ -52,23 +62,53 @@ def main(argv):
' --device_id')
return -1

if args[0] == 'ps':
_ListProcesses(options.backend, device_id,
options.filter_process_name)
return 0
device = backends.GetDevice(options.backend, device_id)
if not device:
print 'Device', device_id, 'does not exist'
return -1

if args[0] == 'stats':
if not options.process_id:
print 'You need to provide --process_id'
return -1
device.Initialize()
if args[0] == 'ps':
if not options.filter_process_name:
print 'Listing all processes'
else:
_ListProcessStats(options.backend, device_id,
options.process_id)
print ('Listing processes matching '
+ options.filter_process_name.lower())
print ''
print '%-10s : %-50s : %12s %12s %12s' % (
'Process ID', 'Process Name', 'RUN_TIME', 'THREADS',
'MEM_RSS_KB')
print ''
for process in device.ListProcesses():
if (not options.filter_process_name or
options.filter_process_name.lower() in process.name.lower()):
stats = process.GetStats()
run_time_min, run_time_sec = divmod(stats.run_time, 60)
print '%10s : %-50s : %6s m %2s s %8s %12s' % (
process.pid, process.name, run_time_min, run_time_sec,
stats.threads, stats.vm_rss)
return 0
else:
print 'Invalid command entered'

if not options.process_id:
print 'You need to provide --process_id'
return -1

process = device.GetProcess(options.process_id)

if not process:
print 'Cannot find process [%d] on device %s' % (
options.process_id, device.id)
return -1
elif args[0] == 'stats':
_ListProcessStats(process)
return 0
elif args[0] == 'mmaps':
_ListProcessMmaps(process)
return 0
elif args[0] == 'classified_mmaps':
_ListProcessClassifiedMmaps(process, options.mmap_rule)
return 0


def _ListDevices(backend_name):
print 'Device list:'
Expand All @@ -78,71 +118,51 @@ def _ListDevices(backend_name):
print '%-16s : %s' % (device.id, device.name)


def _ListProcesses(backend_name, device_id, filter_process_name):
device = backends.GetDevice(backend_name, device_id)
if not device:
print 'Device', device_id, 'does not exist'
return
if not filter_process_name:
print 'Listing all processes'
else:
print 'Listing processes matching ' + filter_process_name.lower()
print ''
device.Initialize()
_PrintProcessHeadingLine()
for process in device.ListProcesses():
if (not filter_process_name or
filter_process_name.lower() in process.name.lower()):
stats = process.GetStats()
_PrintProcess(process, stats)


def _ListProcessStats(backend_name, device_id, process_id):
"""Prints process stats periodically and displays an error if the
process or device does not exist.
def _ListProcessStats(process):
"""Prints process stats periodically
"""
device = backends.GetDevice(backend_name, device_id)
if not device:
print 'Device', device_id, 'does not exist'
else:
device.Initialize()
process = device.GetProcess(process_id)
if not process:
print 'Cannot find process [%d] on device %s' % (
process_id, device_id)
return
print 'Stats for process: [%d] %s' % (process_id, process.name)
_PrintProcessStatsHeadingLine()
while True:
stats = process.GetStats()
_PrintProcessStats(process, stats)
time.sleep(1)


def _PrintProcessHeadingLine():
print '%-10s : %-50s : %12s %12s %12s' % (
'Process ID', 'Process Name', 'RUN_TIME', 'THREADS','MEM_RSS_KB')
print 'Stats for process: [%d] %s' % (process.pid, process.name)
print '%-10s : %-50s : %12s %12s %13s %12s %14s' % (
'Process ID', 'Process Name', 'RUN_TIME', 'THREADS',
'CPU_USAGE', 'MEM_RSS_KB', 'PAGE_FAULTS')
print ''
while True:
stats = process.GetStats()
run_time_min, run_time_sec = divmod(stats.run_time, 60)
print '%10s : %-50s : %6s m %2s s %8s %12s %13s %11s' % (
process.pid, process.name, run_time_min, run_time_sec,
stats.threads, stats.cpu_usage, stats.vm_rss, stats.page_faults)
time.sleep(1)


def _PrintProcess(process, stats):
run_time_min, run_time_sec = divmod(stats.run_time, 60)
print '%10s : %-50s : %6s m %2s s %8s %12s' % (
process.pid, process.name, run_time_min, run_time_sec,
stats.threads, stats.vm_rss)


def _PrintProcessStatsHeadingLine():
print '%-10s : %-50s : %12s %12s %13s %12s %14s' % (
'Process ID', 'Process Name', 'RUN_TIME', 'THREADS',
'CPU_USAGE', 'MEM_RSS_KB', 'PAGE_FAULTS')
def _ListProcessMmaps(process):
"""Prints process memory maps
"""
print 'Memory Maps for process: [%d] %s' % (process.pid, process.name)
print '%-10s %-10s %6s %12s %12s %13s %13s %-40s' % (
'START', 'END', 'FLAGS', 'PRIV.DIRTY', 'PRIV.CLEAN',
'SHARED DIRTY', 'SHARED CLEAN', 'MAPPED_FILE')
print '%38s %12s %12s %13s' % ('(kb)', '(kb)', '(kb)', '(kb)')
print ''
maps = process.DumpMemoryMaps()
for entry in maps.entries:
print '%-10x %-10x %6s %12s %12s %13s %13s %-40s' % (
entry.start, entry.end, entry.prot_flags,
entry.priv_dirty_bytes / 1024, entry.priv_clean_bytes / 1024,
entry.shared_dirty_bytes / 1024,
entry.shared_clean_bytes / 1024, entry.mapped_file)


def _PrintProcessStats(process, stats):
run_time_min, run_time_sec = divmod(stats.run_time, 60)
print '%10s : %-50s : %6s m %2s s %8s %12s %13s %11s' % (
process.pid, process.name, run_time_min, run_time_sec,
stats.threads, stats.cpu_usage, stats.vm_rss, stats.page_faults)
def _ListProcessClassifiedMmaps(process, mmap_rule):
"""Prints process classified memory maps
"""
maps = process.DumpMemoryMaps()
if not os.path.exists(mmap_rule):
print 'File', mmap_rule, 'not found'
return
with open(mmap_rule) as f:
rules = mmap_classifier.LoadRules(f.read())
classified_results_tree = mmap_classifier.Classify(maps, rules)
print json.dumps(classified_results_tree, cls=serialization.Encoder)


2 changes: 1 addition & 1 deletion tools/memory_inspector/memory_inspector_cli
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ from memory_inspector.frontends import command_line


if __name__ == '__main__':
sys.exit(command_line.main(sys.argv))
sys.exit(command_line.main())

0 comments on commit 9f0c7f5

Please sign in to comment.