Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / linux_based_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 try:
6   import resource  # pylint: disable=F0401
7 except ImportError:
8   resource = None  # Not available on all platforms
9
10 from telemetry import decorators
11 from telemetry.core import exceptions
12 from telemetry.core.platform import platform_backend
13
14
15 class LinuxBasedPlatformBackend(platform_backend.PlatformBackend):
16
17   """Abstract platform containing functionality shared by all linux based OSes.
18
19   Subclasses must implement RunCommand, GetFileContents, GetPsOutput, and
20   ParseCStateSample."""
21
22   def GetSystemCommitCharge(self):
23     meminfo_contents = self.GetFileContents('/proc/meminfo')
24     meminfo = self._GetProcFileDict(meminfo_contents)
25     if not meminfo:
26       return None
27     return (self._ConvertKbToByte(meminfo['MemTotal'])
28             - self._ConvertKbToByte(meminfo['MemFree'])
29             - self._ConvertKbToByte(meminfo['Buffers'])
30             - self._ConvertKbToByte(meminfo['Cached']))
31
32   @decorators.Cache
33   def GetSystemTotalPhysicalMemory(self):
34     meminfo_contents = self.GetFileContents('/proc/meminfo')
35     meminfo = self._GetProcFileDict(meminfo_contents)
36     if not meminfo:
37       return None
38     return self._ConvertKbToByte(meminfo['MemTotal'])
39
40   def GetCpuStats(self, pid):
41     stats = self._GetProcFileForPid(pid, 'stat')
42     if not stats:
43       return {}
44     stats = stats.split()
45     utime = float(stats[13])
46     stime = float(stats[14])
47     cpu_process_jiffies = utime + stime
48     return {'CpuProcessTime': cpu_process_jiffies}
49
50   def GetCpuTimestamp(self):
51     timer_list = self.GetFileContents('/proc/timer_list')
52     total_jiffies = float(self._GetProcJiffies(timer_list))
53     return {'TotalTime': total_jiffies}
54
55   def GetMemoryStats(self, pid):
56     status_contents = self._GetProcFileForPid(pid, 'status')
57     stats = self._GetProcFileForPid(pid, 'stat').split()
58     status = self._GetProcFileDict(status_contents)
59     if not status or not stats or 'Z' in status['State']:
60       return {}
61     vm = int(stats[22])
62     vm_peak = (self._ConvertKbToByte(status['VmPeak'])
63                if 'VmPeak' in status else vm)
64     wss = int(stats[23]) * resource.getpagesize()
65     wss_peak = (self._ConvertKbToByte(status['VmHWM'])
66                 if 'VmHWM' in status else wss)
67
68     private_dirty_bytes = 0
69     for line in self._GetProcFileForPid(pid, 'smaps').splitlines():
70       if line.startswith('Private_Dirty:'):
71         private_dirty_bytes += self._ConvertKbToByte(line.split(':')[1].strip())
72
73     return {'VM': vm,
74             'VMPeak': vm_peak,
75             'PrivateDirty': private_dirty_bytes,
76             'WorkingSetSize': wss,
77             'WorkingSetSizePeak': wss_peak}
78
79   def GetIOStats(self, pid):
80     io_contents = self._GetProcFileForPid(pid, 'io')
81     io = self._GetProcFileDict(io_contents)
82     return {'ReadOperationCount': int(io['syscr']),
83             'WriteOperationCount': int(io['syscw']),
84             'ReadTransferCount': int(io['rchar']),
85             'WriteTransferCount': int(io['wchar'])}
86
87   def GetFileContents(self, filename):
88     raise NotImplementedError()
89
90   def GetPsOutput(self, columns, pid=None):
91     raise NotImplementedError()
92
93   def RunCommand(self, cmd):
94     raise NotImplementedError()
95
96   @staticmethod
97   def ParseCStateSample(sample):
98     """Parse a single c-state residency sample.
99
100     Args:
101         sample: A sample of c-state residency times to be parsed. Organized as
102             a dictionary mapping CPU name to a string containing all c-state
103             names, the times in each state, the latency of each state, and the
104             time at which the sample was taken all separated by newlines.
105             Ex: {'cpu0': 'C0\nC1\n5000\n2000\n20\n30\n1406673171'}
106
107     Returns:
108         Dictionary associating a c-state with a time.
109     """
110     raise NotImplementedError()
111
112   def _IsPidAlive(self, pid):
113     assert pid, 'pid is required'
114     return bool(self.GetPsOutput(['pid'], pid) == str(pid))
115
116   def _GetProcFileForPid(self, pid, filename):
117     try:
118       return self.GetFileContents('/proc/%s/%s' % (pid, filename))
119     except IOError:
120       if not self._IsPidAlive(pid):
121         raise exceptions.ProcessGoneException()
122       raise
123
124   def _ConvertKbToByte(self, value):
125     return int(value.replace('kB','')) * 1024
126
127   def _GetProcFileDict(self, contents):
128     retval = {}
129     for line in contents.splitlines():
130       key, value = line.split(':')
131       retval[key.strip()] = value.strip()
132     return retval
133
134   def _GetProcJiffies(self, timer_list):
135     """Parse '/proc/timer_list' output and returns the first jiffies attribute.
136
137     Multi-CPU machines will have multiple 'jiffies:' lines, all of which will be
138     essentially the same.  Return the first one."""
139     if isinstance(timer_list, str):
140       timer_list = timer_list.splitlines()
141     for line in timer_list:
142       if line.startswith('jiffies:'):
143         _, value = line.split(':')
144         return value
145     raise Exception('Unable to find jiffies from /proc/timer_list')