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