Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / profiler / tcmalloc_heap_profiler.py
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.
4
5 import logging
6 import os
7 import sys
8
9 from telemetry.core.backends.chrome import android_browser_finder
10 from telemetry.core.platform import profiler
11
12 # Enviroment variables to (android properties, default value) mapping.
13 _ENV_VARIABLES = {
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),
17 }
18
19
20 class _TCMallocHeapProfilerAndroid(object):
21   """An internal class to set android properties and fetch dumps from device."""
22
23   _DEFAULT_DEVICE_DIR = '/data/local/tmp/heap'
24
25   def __init__(self, browser_backend, output_path):
26     self._browser_backend = browser_backend
27     self._output_path = output_path
28
29     _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof',
30         os.path.join(self._DEFAULT_DEVICE_DIR, 'dmprof'))
31
32     self._SetDeviceProperties(_ENV_VARIABLES)
33
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
50     if device_configured:
51       raise Exception('Device required special config, run again.')
52
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]
64
65
66 class _TCMallocHeapProfilerLinux(object):
67   """An internal class to set environment variables and fetch dumps."""
68
69   _DEFAULT_DIR = '/tmp/tcmalloc/'
70
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)
75
76   def _CheckEnvironmentVariables(self, env_vars):
77     msg = ''
78     for key, values in env_vars.iteritems():
79       if key not in os.environ:
80         msg += '%s=%s ' % (key, str(values[1]))
81     if msg:
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'
86
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']]
93
94
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)
103     else:
104       self._platform_profiler = _TCMallocHeapProfilerLinux(browser_backend)
105
106   @classmethod
107   def name(cls):
108     return 'tcmalloc-heap'
109
110   @classmethod
111   def is_supported(cls, browser_type):
112     if browser_type.startswith('cros'):
113       return False
114     if sys.platform.startswith('linux'):
115       return True
116     if browser_type == 'any':
117       return android_browser_finder.CanFindAvailableBrowsers()
118     return browser_type.startswith('android')
119
120   @classmethod
121   def CustomizeBrowserOptions(cls, browser_type, options):
122     options.AppendExtraBrowserArgs('--no-sandbox')
123     options.AppendExtraBrowserArgs('--enable-memory-benchmarking')
124
125   @classmethod
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');
136         }
137       """)
138
139   def CollectProfile(self):
140     return self._platform_profiler.CollectProfile()