1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
9 from telemetry.core.backends.chrome import android_browser_finder
10 from telemetry.core.platform import profiler
12 # Enviroment variables to (android properties, default value) mapping.
14 'HEAP_PROFILE_TIME_INTERVAL': ('heapprof.time_interval', 20),
15 'HEAP_PROFILE_MMAP': ('heapprof.mmap', 1),
16 'DEEP_HEAP_PROFILE': ('heapprof.deep_heap_profile', 1),
20 class _TCMallocHeapProfilerAndroid(object):
21 """An internal class to set android properties and fetch dumps from device."""
23 _DEFAULT_DEVICE_DIR = '/data/local/tmp/heap'
25 def __init__(self, browser_backend, output_path):
26 self._browser_backend = browser_backend
27 self._output_path = output_path
29 _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof',
30 os.path.join(self._DEFAULT_DEVICE_DIR, 'dmprof'))
32 self._SetDeviceProperties(_ENV_VARIABLES)
34 def _SetDeviceProperties(self, properties):
35 device_configured = False
36 # This profiler requires adb root to set properties.
37 self._browser_backend.adb.device().old_interface.EnableAdbRoot()
38 for values in properties.itervalues():
39 device_property = self._browser_backend.adb.device().GetProp(values[0])
40 if not device_property or not device_property.strip():
41 self._browser_backend.adb.device().SetProp(values[0], values[1])
42 device_configured = True
43 if not self._browser_backend.adb.device().FileExists(
44 self._DEFAULT_DEVICE_DIR):
45 self._browser_backend.adb.RunShellCommand(
46 'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
47 self._browser_backend.adb.RunShellCommand(
48 'chmod 777 ' + self._DEFAULT_DEVICE_DIR)
49 device_configured = True
51 raise Exception('Device required special config, run again.')
53 def CollectProfile(self):
54 self._browser_backend.adb.device().old_interface.Adb().Pull(
55 self._DEFAULT_DEVICE_DIR, self._output_path)
56 self._browser_backend.adb.RunShellCommand(
57 'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
58 if os.path.exists(self._output_path):
59 logging.info('TCMalloc dumps pulled to %s', self._output_path)
60 with file(os.path.join(self._output_path,
61 'browser.pid'), 'w') as pid_file:
62 pid_file.write(str(self._browser_backend.pid).rjust(5, '0'))
63 return [self._output_path]
66 class _TCMallocHeapProfilerLinux(object):
67 """An internal class to set environment variables and fetch dumps."""
69 _DEFAULT_DIR = '/tmp/tcmalloc/'
71 def __init__(self, browser_backend):
72 self._browser_backend = browser_backend
73 _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof', self._DEFAULT_DIR + 'dmprof')
74 self._CheckEnvironmentVariables(_ENV_VARIABLES)
76 def _CheckEnvironmentVariables(self, env_vars):
78 for key, values in env_vars.iteritems():
79 if key not in os.environ:
80 msg += '%s=%s ' % (key, str(values[1]))
82 raise Exception('Need enviroment variables, try again with:\n %s' % msg)
83 if not os.path.exists(os.environ['HEAPPROFILE']):
84 os.makedirs(os.environ['HEAPPROFILE'])
85 assert os.path.isdir(os.environ['HEAPPROFILE']), 'HEAPPROFILE is not a dir'
87 def CollectProfile(self):
88 with file(os.path.join(os.path.dirname(os.environ['HEAPPROFILE']),
89 'browser.pid'), 'w') as pid_file:
90 pid_file.write(str(self._browser_backend.pid))
91 print 'TCMalloc dumps available ', os.environ['HEAPPROFILE']
92 return [os.environ['HEAPPROFILE']]
95 class TCMallocHeapProfiler(profiler.Profiler):
96 """A Factory to instantiate the platform-specific profiler."""
97 def __init__(self, browser_backend, platform_backend, output_path, state):
98 super(TCMallocHeapProfiler, self).__init__(
99 browser_backend, platform_backend, output_path, state)
100 if platform_backend.GetOSName() == 'android':
101 self._platform_profiler = _TCMallocHeapProfilerAndroid(
102 browser_backend, output_path)
104 self._platform_profiler = _TCMallocHeapProfilerLinux(browser_backend)
108 return 'tcmalloc-heap'
111 def is_supported(cls, browser_type):
112 if browser_type.startswith('cros'):
114 if sys.platform.startswith('linux'):
116 if browser_type == 'any':
117 return android_browser_finder.CanFindAvailableBrowsers()
118 return browser_type.startswith('android')
121 def CustomizeBrowserOptions(cls, browser_type, options):
122 options.AppendExtraBrowserArgs('--no-sandbox')
123 options.AppendExtraBrowserArgs('--enable-memory-benchmarking')
126 def WillCloseBrowser(cls, browser_backend, platform_backend):
127 # The tcmalloc_heap_profiler dumps files at regular
128 # intervals (~20 secs).
129 # This is a minor optimization to ensure it'll dump the last file when
130 # the test completes.
131 for i in xrange(len(browser_backend.browser.tabs)):
132 browser_backend.browser.tabs[i].ExecuteJavaScript("""
133 if (chrome && chrome.memoryBenchmarking) {
134 chrome.memoryBenchmarking.heapProfilerDump('renderer', 'final');
135 chrome.memoryBenchmarking.heapProfilerDump('browser', 'final');
139 def CollectProfile(self):
140 return self._platform_profiler.CollectProfile()