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..e392cb0b060bfd06a9b039ab4b8be0c517770a4c |
--- /dev/null |
+++ b/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py |
@@ -0,0 +1,117 @@ |
+# 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 logging |
+import os |
+import sys |
+ |
+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(object): |
+ """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): |
+ self._browser_backend = browser_backend |
+ self._output_path = output_path |
+ |
+ _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof', |
+ os.path.join(self._DEFAULT_DEVICE_DIR, 'dmprof')) |
+ |
+ self._SetDeviceProperties(_ENV_VARIABLES) |
+ |
+ def _SetDeviceProperties(self, properties): |
+ device_configured = False |
+ for values in properties.itervalues(): |
+ device_property = self._browser_backend.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] |
+ self._browser_backend.adb.RunShellCommand( |
+ 'setprop ' + values[0] + ' ' + str(values[1])) |
+ device_configured = True |
+ if not self._browser_backend.adb.Adb().FileExistsOnDevice( |
+ self._DEFAULT_DEVICE_DIR): |
+ self._browser_backend.adb.RunShellCommand( |
+ 'mkdir -p ' + self._DEFAULT_DEVICE_DIR) |
+ self._browser_backend.adb.RunShellCommand( |
+ 'chmod 777 ' + self._DEFAULT_DEVICE_DIR) |
+ device_configured = True |
+ if device_configured: |
+ raise Exception('Device required special config, run again.') |
+ |
+ def CollectProfile(self): |
+ self._browser_backend.adb.Adb().Adb().Pull( |
+ self._DEFAULT_DEVICE_DIR, self._output_path) |
+ self._browser_backend.adb.RunShellCommand( |
+ 'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*')) |
+ if os.path.exists(self._output_path): |
+ logging.info('TCMalloc dumps pulled to %s', self._output_path) |
+ with file(os.path.join(self._output_path, |
+ 'browser.pid'), 'w') as pid_file: |
+ pid_file.write(str(self._browser_backend.pid).rjust(5, '0')) |
+ |
+ |
+class _TCMallocHeapProfilerLinux(object): |
+ """An internal class to set environment variables and fetch dumps.""" |
+ |
+ _DEFAULT_DIR = '/tmp/tcmalloc/' |
+ |
+ def __init__(self, browser_backend): |
+ self._browser_backend = browser_backend |
+ _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof', self._DEFAULT_DIR + 'dmprof') |
+ self._CheckEnvironmentVariables(_ENV_VARIABLES) |
+ |
+ 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']): |
+ os.makedirs(os.environ['HEAPPROFILE']) |
+ assert os.path.isdir(os.environ['HEAPPROFILE']), 'HEAPPROFILE is not a dir' |
+ |
+ def CollectProfile(self): |
+ with file(os.path.join(os.path.dirname(os.environ['HEAPPROFILE']), |
+ 'browser.pid'), 'w') as pid_file: |
+ pid_file.write(str(self._browser_backend.pid)) |
+ print 'TCMalloc dumps available ', os.environ['HEAPPROFILE'] |
+ |
+ |
+class TCMallocHeapProfiler(profiler.Profiler): |
+ """A Factory to instantiate the platform-specific profiler.""" |
+ def __init__(self, browser_backend, platform_backend, output_path): |
+ super(TCMallocHeapProfiler, self).__init__( |
+ browser_backend, platform_backend, output_path) |
+ if self._browser_backend.options.browser_type.startswith('android'): |
+ self._platform_profiler = _TCMallocHeapProfilerAndroid( |
+ browser_backend, output_path) |
+ else: |
+ self._platform_profiler = _TCMallocHeapProfilerLinux(browser_backend) |
+ |
+ @classmethod |
+ def name(cls): |
+ return 'tcmalloc-heap' |
+ |
+ @classmethod |
+ def is_supported(cls, options): |
+ if (not sys.platform.startswith('linux') or |
+ options.browser_type.startswith('cros')): |
+ return False |
+ return True |
+ |
+ def CollectProfile(self): |
+ self._platform_profiler.CollectProfile() |