1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)try: 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) import resource # pylint: disable=F0401 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)except ImportError: 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) resource = None # Not available on all platforms 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from telemetry import decorators 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)from telemetry.core import exceptions 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)from telemetry.core.platform import platform_backend 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass LinuxBasedPlatformBackend(platform_backend.PlatformBackend): 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """Abstract platform containing functionality shared by all linux based OSes. 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Subclasses must implement RunCommand, GetFileContents, GetPsOutput, and 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ParseCStateSample.""" 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def GetSystemCommitCharge(self): 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci meminfo_contents = self.GetFileContents('/proc/meminfo') 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) meminfo = self._GetProcFileDict(meminfo_contents) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not meminfo: 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return (self._ConvertKbToByte(meminfo['MemTotal']) 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) - self._ConvertKbToByte(meminfo['MemFree']) 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) - self._ConvertKbToByte(meminfo['Buffers']) 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) - self._ConvertKbToByte(meminfo['Cached'])) 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @decorators.Cache 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetSystemTotalPhysicalMemory(self): 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci meminfo_contents = self.GetFileContents('/proc/meminfo') 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) meminfo = self._GetProcFileDict(meminfo_contents) 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not meminfo: 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return self._ConvertKbToByte(meminfo['MemTotal']) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def GetCpuStats(self, pid): 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stats = self._GetProcFileForPid(pid, 'stat') 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not stats: 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return {} 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stats = stats.split() 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) utime = float(stats[13]) 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stime = float(stats[14]) 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) cpu_process_jiffies = utime + stime 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return {'CpuProcessTime': cpu_process_jiffies} 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def GetCpuTimestamp(self): 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci timer_list = self.GetFileContents('/proc/timer_list') 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) total_jiffies = float(self._GetProcJiffies(timer_list)) 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return {'TotalTime': total_jiffies} 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def GetMemoryStats(self, pid): 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) status_contents = self._GetProcFileForPid(pid, 'status') 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stats = self._GetProcFileForPid(pid, 'stat').split() 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) status = self._GetProcFileDict(status_contents) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not status or not stats or 'Z' in status['State']: 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return {} 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) vm = int(stats[22]) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) vm_peak = (self._ConvertKbToByte(status['VmPeak']) 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if 'VmPeak' in status else vm) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wss = int(stats[23]) * resource.getpagesize() 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) wss_peak = (self._ConvertKbToByte(status['VmHWM']) 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if 'VmHWM' in status else wss) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private_dirty_bytes = 0 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for line in self._GetProcFileForPid(pid, 'smaps').splitlines(): 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if line.startswith('Private_Dirty:'): 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private_dirty_bytes += self._ConvertKbToByte(line.split(':')[1].strip()) 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return {'VM': vm, 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 'VMPeak': vm_peak, 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 'PrivateDirty': private_dirty_bytes, 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 'WorkingSetSize': wss, 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 'WorkingSetSizePeak': wss_peak} 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def GetIOStats(self, pid): 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) io_contents = self._GetProcFileForPid(pid, 'io') 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) io = self._GetProcFileDict(io_contents) 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return {'ReadOperationCount': int(io['syscr']), 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 'WriteOperationCount': int(io['syscw']), 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 'ReadTransferCount': int(io['rchar']), 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 'WriteTransferCount': int(io['wchar'])} 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetFileContents(self, filename): 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) raise NotImplementedError() 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def GetPsOutput(self, columns, pid=None): 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raise NotImplementedError() 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def RunCommand(self, cmd): 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raise NotImplementedError() 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @staticmethod 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def ParseCStateSample(sample): 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """Parse a single c-state residency sample. 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Args: 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sample: A sample of c-state residency times to be parsed. Organized as 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci a dictionary mapping CPU name to a string containing all c-state 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci names, the times in each state, the latency of each state, and the 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci time at which the sample was taken all separated by newlines. 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Ex: {'cpu0': 'C0\nC1\n5000\n2000\n20\n30\n1406673171'} 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Returns: 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Dictionary associating a c-state with a time. 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """ 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) raise NotImplementedError() 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def _IsPidAlive(self, pid): 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) assert pid, 'pid is required' 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return bool(self.GetPsOutput(['pid'], pid) == str(pid)) 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def _GetProcFileForPid(self, pid, filename): 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) try: 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return self.GetFileContents('/proc/%s/%s' % (pid, filename)) 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) except IOError: 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not self._IsPidAlive(pid): 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) raise exceptions.ProcessGoneException() 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) raise 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def _ConvertKbToByte(self, value): 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return int(value.replace('kB','')) * 1024 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def _GetProcFileDict(self, contents): 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) retval = {} 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for line in contents.splitlines(): 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key, value = line.split(':') 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) retval[key.strip()] = value.strip() 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return retval 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def _GetProcJiffies(self, timer_list): 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """Parse '/proc/timer_list' output and returns the first jiffies attribute. 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Multi-CPU machines will have multiple 'jiffies:' lines, all of which will be 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) essentially the same. Return the first one.""" 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if isinstance(timer_list, str): 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) timer_list = timer_list.splitlines() 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for line in timer_list: 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if line.startswith('jiffies:'): 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) _, value = line.split(':') 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return value 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) raise Exception('Unable to find jiffies from /proc/timer_list') 146