Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / mac_platform_backend.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 ctypes
6 import os
7 import platform
8 import time
9
10 from telemetry import decorators
11 from telemetry.core.platform import platform_backend
12 from telemetry.core.platform import posix_platform_backend
13 from telemetry.core.platform import process_statistic_timeline_data
14 from telemetry.core.platform.power_monitor import powermetrics_power_monitor
15
16 try:
17   import resource  # pylint: disable=F0401
18 except ImportError:
19   resource = None  # Not available on all platforms
20
21
22
23 class MacPlatformBackend(posix_platform_backend.PosixPlatformBackend):
24   def __init__(self):
25     super(MacPlatformBackend, self).__init__()
26     self.libproc = None
27     self._power_monitor = powermetrics_power_monitor.PowerMetricsPowerMonitor(
28         self)
29
30   def StartRawDisplayFrameRateMeasurement(self):
31     raise NotImplementedError()
32
33   def StopRawDisplayFrameRateMeasurement(self):
34     raise NotImplementedError()
35
36   def GetRawDisplayFrameRateMeasurements(self):
37     raise NotImplementedError()
38
39   def IsThermallyThrottled(self):
40     raise NotImplementedError()
41
42   def HasBeenThermallyThrottled(self):
43     raise NotImplementedError()
44
45   def _GetIdleWakeupCount(self, pid):
46     top_output = self._GetTopOutput(pid, ['idlew'])
47
48     # Sometimes top won't return anything here, just ignore such cases -
49     # crbug.com/354812 .
50     if top_output[-2] != 'IDLEW':
51       return process_statistic_timeline_data.IdleWakeupTimelineData(pid, 0)
52     # Numbers reported by top may have a '+' appended.
53     wakeup_count = int(top_output[-1].strip('+ '))
54     return process_statistic_timeline_data.IdleWakeupTimelineData(pid,
55         wakeup_count)
56
57   def GetCpuStats(self, pid):
58     """Returns a dict of cpu statistics for the process represented by |pid|."""
59     class ProcTaskInfo(ctypes.Structure):
60       """Struct for proc_pidinfo() call."""
61       _fields_ = [("pti_virtual_size", ctypes.c_uint64),
62                   ("pti_resident_size", ctypes.c_uint64),
63                   ("pti_total_user", ctypes.c_uint64),
64                   ("pti_total_system", ctypes.c_uint64),
65                   ("pti_threads_user", ctypes.c_uint64),
66                   ("pti_threads_system", ctypes.c_uint64),
67                   ("pti_policy", ctypes.c_int32),
68                   ("pti_faults", ctypes.c_int32),
69                   ("pti_pageins", ctypes.c_int32),
70                   ("pti_cow_faults", ctypes.c_int32),
71                   ("pti_messages_sent", ctypes.c_int32),
72                   ("pti_messages_received", ctypes.c_int32),
73                   ("pti_syscalls_mach", ctypes.c_int32),
74                   ("pti_syscalls_unix", ctypes.c_int32),
75                   ("pti_csw", ctypes.c_int32),
76                   ("pti_threadnum", ctypes.c_int32),
77                   ("pti_numrunning", ctypes.c_int32),
78                   ("pti_priority", ctypes.c_int32)]
79       PROC_PIDTASKINFO = 4
80       def __init__(self):
81         self.size = ctypes.sizeof(self)
82         super(ProcTaskInfo, self).__init__()
83
84     proc_info = ProcTaskInfo()
85     if not self.libproc:
86       self.libproc = ctypes.CDLL(ctypes.util.find_library('libproc'))
87     self.libproc.proc_pidinfo(pid, proc_info.PROC_PIDTASKINFO, 0,
88                               ctypes.byref(proc_info), proc_info.size)
89
90     # Convert nanoseconds to seconds.
91     cpu_time = (proc_info.pti_total_user / 1000000000.0 +
92                 proc_info.pti_total_system / 1000000000.0)
93     results = {'CpuProcessTime': cpu_time,
94                'ContextSwitches': proc_info.pti_csw}
95
96     # top only reports idle wakeup count starting from OS X 10.9.
97     if self.GetOSVersionName() >= platform_backend.MAVERICKS:
98       results.update({'IdleWakeupCount': self._GetIdleWakeupCount(pid)})
99     return results
100
101   def GetCpuTimestamp(self):
102     """Return current timestamp in seconds."""
103     return {'TotalTime': time.time()}
104
105   def GetSystemCommitCharge(self):
106     vm_stat = self.RunCommand(['vm_stat'])
107     for stat in vm_stat.splitlines():
108       key, value = stat.split(':')
109       if key == 'Pages active':
110         pages_active = int(value.strip()[:-1])  # Strip trailing '.'
111         return pages_active * resource.getpagesize() / 1024
112     return 0
113
114   @decorators.Cache
115   def GetSystemTotalPhysicalMemory(self):
116     return int(self.RunCommand(['sysctl', '-n', 'hw.memsize']))
117
118   def PurgeUnpinnedMemory(self):
119     # TODO(pliard): Implement this.
120     pass
121
122   def GetMemoryStats(self, pid):
123     rss_vsz = self.GetPsOutput(['rss', 'vsz'], pid)
124     if rss_vsz:
125       rss, vsz = rss_vsz[0].split()
126       return {'VM': 1024 * int(vsz),
127               'WorkingSetSize': 1024 * int(rss)}
128     return {}
129
130   @decorators.Cache
131   def GetArchName(self):
132     return platform.machine()
133
134   def GetOSName(self):
135     return 'mac'
136
137   @decorators.Cache
138   def GetOSVersionName(self):
139     os_version = os.uname()[2]
140
141     if os_version.startswith('9.'):
142       return platform_backend.LEOPARD
143     if os_version.startswith('10.'):
144       return platform_backend.SNOWLEOPARD
145     if os_version.startswith('11.'):
146       return platform_backend.LION
147     if os_version.startswith('12.'):
148       return platform_backend.MOUNTAINLION
149     if os_version.startswith('13.'):
150       return platform_backend.MAVERICKS
151     if os_version.startswith('14.'):
152       return platform_backend.YOSEMITE
153
154     raise NotImplementedError('Unknown mac version %s.' % os_version)
155
156   def CanFlushIndividualFilesFromSystemCache(self):
157     return False
158
159   def FlushEntireSystemCache(self):
160     mavericks_or_later = self.GetOSVersionName() >= platform_backend.MAVERICKS
161     p = self.LaunchApplication('purge', elevate_privilege=mavericks_or_later)
162     p.communicate()
163     assert p.returncode == 0, 'Failed to flush system cache'
164
165   def CanMonitorPower(self):
166     return self._power_monitor.CanMonitorPower()
167
168   def CanMeasurePerApplicationPower(self):
169     return self._power_monitor.CanMeasurePerApplicationPower()
170
171   def StartMonitoringPower(self, browser):
172     self._power_monitor.StartMonitoringPower(browser)
173
174   def StopMonitoringPower(self):
175     return self._power_monitor.StopMonitoringPower()