Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Unified Diff: tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py

Issue 15093008: Telemetry: integrates memory_measurement with TCMalloc dumps (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: TCMallocHeapProfiler Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
diff --git a/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f7e767f104221a41ee4ebcba7b979b79f3d4d49
--- /dev/null
+++ b/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
@@ -0,0 +1,125 @@
+# Copyright (c) 2013 The Chromium 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 os
+import sys
+
+from telemetry.core.chrome import adb_commands
+from telemetry.core.platform import profiler
+
+# Enviroment variables to (android properties, default value) mapping.
+_ENV_VARIABLES = {
+ 'HEAP_PROFILE_TIME_INTERVAL': ('heapprof.time_interval', 20),
+ 'HEAP_PROFILE_MMAP': ('heapprof.mmap', 1),
+ 'DEEP_HEAP_PROFILE': ('heapprof.deep_heap_profile', 1),
+}
+
+class _TCMallocHeapProfilerAndroid(profiler.Profiler):
tonyg 2013/05/14 16:52:44 Can these just implement object instead of Profile
bulach 2013/05/14 17:54:47 oh, much nicer! done.
+ """An internal class to set android properties and fetch dumps from device."""
+
+ _DEFAULT_DEVICE_DIR = '/data/local/tmp/heap/'
+
+ def __init__(self, browser_backend, _, output_path):
+ super(_TCMallocHeapProfilerAndroid, self).__init__(output_path)
+ self._browser_backend = browser_backend
+
+ properties = dict(_ENV_VARIABLES)
+ properties['HEAPPROFILE'] = ('heapprof',
+ self._DEFAULT_DEVICE_DIR + 'dmprof')
+
+ self._SetDeviceProperties(self._browser_backend.options.android_device,
+ properties)
+
+ def _SetDeviceProperties(self, android_device, properties):
+ adb = adb_commands.AdbCommands(android_device)
tonyg 2013/05/14 16:52:44 I didn't double check, but can't we get an existin
bulach 2013/05/14 17:54:47 Done.
+ has_set_property = False
+ for values in properties.itervalues():
+ device_property = adb.RunShellCommand('getprop ' + values[0])
+ if (not device_property or len(device_property) != 1 or
+ not device_property[0].strip()):
+ print 'Setting device property ', values[0], values[1]
tonyg 2013/05/14 16:52:44 logging.info?
bulach 2013/05/14 17:54:47 Done.
+ adb.RunShellCommand('setprop ' + values[0] + ' ' + str(values[1]))
+ has_set_property = True
+ if has_set_property:
+ raise Exception('New device properties were set, run again.')
tonyg 2013/05/14 16:52:44 Why do we have to run again? Can we do Browser.clo
bulach 2013/05/14 17:54:47 I think at this stage where the profiler has been
tonyg 2013/05/14 18:54:13 You are right, too bad.
+ adb.RunShellCommand('rm -rf ' + self._DEFAULT_DEVICE_DIR)
+ adb.RunShellCommand('mkdir -p ' + self._DEFAULT_DEVICE_DIR)
+ adb.RunShellCommand('chmod 777 ' + self._DEFAULT_DEVICE_DIR)
+
+ @classmethod
+ def name(cls):
+ return 'tcmalloc'
+
+ @classmethod
+ def is_supported(cls, options):
+ return True
+
+ def CollectProfile(self):
+ print 'TCMalloc dumps available in the device ', self._DEFAULT_DEVICE_DIR
tonyg 2013/05/14 16:52:44 Is this print necessary since it will be pulled to
bulach 2013/05/14 17:54:47 Done.
+ adb = adb_commands.AdbCommands(self._browser_backend.options.android_device)
tonyg 2013/05/14 16:52:44 Again, let's try to reuse adb_commands if possible
bulach 2013/05/14 17:54:47 Done.
+ adb.Adb().Adb().Pull(self._DEFAULT_DEVICE_DIR, self.output_path)
+ print 'TCMalloc dumps pulled to ', self.output_path
+
+
+class _TCMallocHeapProfilerLinux(profiler.Profiler):
+ """An internal class to set environment variables and fetch dumps."""
+
+ _DEFAULT_DIR = '/tmp/tcmalloc/'
+
+ def __init__(self, browser_backend, _, output_path):
+ super(_TCMallocHeapProfilerLinux, self).__init__(output_path)
+ self._browser_backend = browser_backend
+
+ env_vars = dict(_ENV_VARIABLES)
tonyg 2013/05/14 16:52:44 What does the dict() wrapper do? Isn't it already
bulach 2013/05/14 17:54:47 at some point I did that in the classmethod and di
+ env_vars['HEAPPROFILE'] = ('heapprof', self._DEFAULT_DIR + 'dmprof')
+ self._CheckEnvironmentVariables(env_vars)
+
+ def _CheckEnvironmentVariables(self, env_vars):
+ msg = ''
+ for key, values in env_vars.iteritems():
+ if key not in os.environ:
+ msg += '%s=%s ' % (key, str(values[1]))
+ if msg:
+ raise Exception('Need enviroment variables, try again with:\n %s' % msg)
+ if not os.path.exists(os.environ['HEAPPROFILE']):
tonyg 2013/05/14 16:52:44 Should we check isdir() as well?
bulach 2013/05/14 17:54:47 adding an assertion below.
+ os.makedirs(os.environ['HEAPPROFILE'])
+
+ @classmethod
+ def name(cls):
+ return 'tcmalloc'
+
+ @classmethod
+ def is_supported(cls, options):
+ return True
+
+ def CollectProfile(self):
+ print 'TCMalloc dumps available ', os.environ['HEAPPROFILE']
+
+
+class TCMallocHeapProfiler(profiler.Profiler):
+ """A Factory to instantiate the platform-specific profiler."""
+ def __init__(self, browser_backend, _, output_path):
+ super(TCMallocHeapProfiler, self).__init__(output_path)
+ self._browser_backend = browser_backend
+ if self._browser_backend.options.browser_type.startswith('android'):
+ self._platform_profiler = _TCMallocHeapProfilerAndroid(
+ browser_backend, _, output_path)
+ else:
+ self._platform_profiler = _TCMallocHeapProfilerLinux(
+ browser_backend, _, output_path)
+
+ @classmethod
+ def name(cls):
+ return 'tcmalloc-heap'
+
+ @classmethod
+ def is_supported(cls, options):
+ if (sys.platform != 'linux2'):
tonyg 2013/05/14 16:52:44 drop the parens. Also, I think we normally do star
bulach 2013/05/14 17:54:47 Done.
bulach 2013/05/14 17:54:47 Done.
+ return False
+ if options.browser_type.startswith('android'):
tonyg 2013/05/14 16:52:44 Do we need to throw in an: if options.browser_typ
bulach 2013/05/14 17:54:47 Done.
+ return _TCMallocHeapProfilerAndroid.is_supported(options)
+ return _TCMallocHeapProfilerLinux.is_supported(options)
tonyg 2013/05/14 16:52:44 These is_supported calls are no-ops. I'd just retu
bulach 2013/05/14 17:54:47 Done.
+
+ def CollectProfile(self):
+ self._platform_profiler.CollectProfile()

Powered by Google App Engine
This is Rietveld 408576698