blob: 529b0af75047f7d155b4fc7e354a1f474fb17ec6 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import os
import paths
import subprocess
import sys
CATEGORIES = [
'dart-codespace',
'dart-oldspace',
'dart-newspace',
'jemalloc-heap',
'pthread_t',
'magma_create_buffer',
'scudo:primary',
'scudo:secondary',
'lib',
]
def FxSSH(address, command):
fx = os.path.join(paths.FUCHSIA_ROOT, 'scripts', 'fx')
cmd = [fx, 'ssh', address] + command
try:
result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print ("command failed: " + ' '.join(cmd) + "\n" +
"output: " + e.output)
return None
return result
def HumanToBytes(size_str):
last = size_str[-1]
KB = 1024
if last == 'B':
multiplier = 1
elif last == 'k':
multiplier = KB
elif last == 'M':
multiplier = KB * KB
elif last == 'G':
multiplier = KB * KB * KB
elif last == 'T':
multiplier = KB * KB * KB * KB
else:
raise Exception('Unknown multiplier ' + last)
return float(size_str[:-1]) * multiplier
def BytesToHuman(num, suffix='B'):
for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
# The output of vmos is:
# rights koid parent #chld #map #shr size alloc name [app]
# on each line
def ParseVmos(vmos, matchers):
vmo_lines = vmos.strip().split('\n')
sizes = {}
koids = {}
for vmo in vmo_lines:
# 1: koid, 5: process sharing, 6: size, 7: alloc, 8: name [9: app]
data = vmo.split()
if len(data) < 9:
continue
name = data[8]
if len(data) >= 10:
name = name + ' ' + data[9]
try:
b = HumanToBytes(data[7])
except:
continue
koid = int(data[1])
if koid in koids:
continue
koids[koid] = True
sharing = int(data[5])
if sharing == 0:
continue
for matcher in matchers:
if matcher not in name:
continue
if matcher in sizes:
sizes[matcher] = sizes[matcher] + (b / sharing)
else:
sizes[matcher] = (b / sharing)
break
if 'total' in sizes:
sizes['total'] = sizes['total'] + (b / sharing)
else:
sizes['total'] = (b / sharing)
return sizes
def Main():
parser = argparse.ArgumentParser('Display stats about Dart VMOs')
parser.add_argument('--pid', '-p',
required=True,
help='pid of the target process.')
parser.add_argument('--address', '-a',
required=True,
help='ipv4 address of the target device')
args = parser.parse_args()
vmos = FxSSH(args.address, ['vmos', args.pid])
sizes = ParseVmos(vmos, CATEGORIES)
for k, v in sizes.iteritems():
print k + ", " + BytesToHuman(v)
return 0
if __name__ == '__main__':
sys.exit(Main())