- add sources.
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / profiler / tcmalloc_heap_profiler.py
1 # Copyright (c) 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.Adb().EnableAdbRoot()
38     for values in properties.itervalues():
39       device_property = self._browser_backend.adb.RunShellCommand(
40           'getprop ' + values[0])
41       if (not device_property or len(device_property) != 1 or
42           not device_property[0].strip()):
43         print 'Setting device property ', values[0], values[1]
44         self._browser_backend.adb.RunShellCommand(
45             'setprop ' + values[0] + ' ' + str(values[1]))
46         device_configured = True
47     if not self._browser_backend.adb.Adb().FileExistsOnDevice(
48         self._DEFAULT_DEVICE_DIR):
49       self._browser_backend.adb.RunShellCommand(
50           'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
51       self._browser_backend.adb.RunShellCommand(
52           'chmod 777 ' + self._DEFAULT_DEVICE_DIR)
53       device_configured = True
54     if device_configured:
55       raise Exception('Device required special config, run again.')
56
57   def CollectProfile(self):
58     self._browser_backend.adb.Adb().Adb().Pull(
59         self._DEFAULT_DEVICE_DIR, self._output_path)
60     self._browser_backend.adb.RunShellCommand(
61         'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
62     if os.path.exists(self._output_path):
63       logging.info('TCMalloc dumps pulled to %s', self._output_path)
64       with file(os.path.join(self._output_path,
65                              'browser.pid'), 'w') as pid_file:
66         pid_file.write(str(self._browser_backend.pid).rjust(5, '0'))
67     return [self._output_path]
68
69
70 class _TCMallocHeapProfilerLinux(object):
71   """An internal class to set environment variables and fetch dumps."""
72
73   _DEFAULT_DIR = '/tmp/tcmalloc/'
74
75   def __init__(self, browser_backend):
76     self._browser_backend = browser_backend
77     _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof', self._DEFAULT_DIR + 'dmprof')
78     self._CheckEnvironmentVariables(_ENV_VARIABLES)
79
80   def _CheckEnvironmentVariables(self, env_vars):
81     msg = ''
82     for key, values in env_vars.iteritems():
83       if key not in os.environ:
84         msg += '%s=%s ' % (key, str(values[1]))
85     if msg:
86       raise Exception('Need enviroment variables, try again with:\n %s' % msg)
87     if not os.path.exists(os.environ['HEAPPROFILE']):
88       os.makedirs(os.environ['HEAPPROFILE'])
89     assert os.path.isdir(os.environ['HEAPPROFILE']), 'HEAPPROFILE is not a dir'
90
91   def CollectProfile(self):
92     with file(os.path.join(os.path.dirname(os.environ['HEAPPROFILE']),
93                            'browser.pid'), 'w') as pid_file:
94       pid_file.write(str(self._browser_backend.pid))
95     print 'TCMalloc dumps available ', os.environ['HEAPPROFILE']
96     return [os.environ['HEAPPROFILE']]
97
98
99 class TCMallocHeapProfiler(profiler.Profiler):
100   """A Factory to instantiate the platform-specific profiler."""
101   def __init__(self, browser_backend, platform_backend, output_path, state):
102     super(TCMallocHeapProfiler, self).__init__(
103         browser_backend, platform_backend, output_path, state)
104     if platform_backend.GetOSName() == 'android':
105       self._platform_profiler = _TCMallocHeapProfilerAndroid(
106           browser_backend, output_path)
107     else:
108       self._platform_profiler = _TCMallocHeapProfilerLinux(browser_backend)
109
110   @classmethod
111   def name(cls):
112     return 'tcmalloc-heap'
113
114   @classmethod
115   def is_supported(cls, browser_type):
116     if browser_type.startswith('cros'):
117       return False
118     if sys.platform.startswith('linux'):
119       return True
120     if browser_type == 'any':
121       return android_browser_finder.CanFindAvailableBrowsers()
122     return browser_type.startswith('android')
123
124   @classmethod
125   def CustomizeBrowserOptions(cls, browser_type, options):
126     options.AppendExtraBrowserArgs('--no-sandbox')
127
128   def CollectProfile(self):
129     return self._platform_profiler.CollectProfile()