| Index: tools/memory_inspector/memory_inspector/frontends/command_line.py
|
| diff --git a/tools/memory_inspector/memory_inspector/frontends/command_line.py b/tools/memory_inspector/memory_inspector/frontends/command_line.py
|
| index d85a2c714ce845773c610fd35122051214a481c8..cfcb7c846263c6134bcad1598ba0a3ec64cf3ffa 100644
|
| --- a/tools/memory_inspector/memory_inspector/frontends/command_line.py
|
| +++ b/tools/memory_inspector/memory_inspector/frontends/command_line.py
|
| @@ -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')
|
| @@ -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
|
| @@ -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:'
|
| @@ -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)
|
|
|
|
|
|
|