1# Copyright (C) 2013-2020 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16import time 17import os 18import gc 19 20class Measure(object): 21 """A class that measure and collect the interesting data for a given testcase. 22 23 An instance of Measure has a collection of measurements, and each 24 of them is to measure a given aspect, such as time and memory. 25 """ 26 27 def __init__(self, measurements): 28 """Constructor of measure. 29 30 measurements is a collection of Measurement objects. 31 """ 32 33 self.measurements = measurements 34 35 def measure(self, func, id): 36 """Measure the operations done by func with a collection of measurements.""" 37 # Enable GC, force GC and disable GC before running test in order to reduce 38 # the interference from GC. 39 gc.enable() 40 gc.collect() 41 gc.disable() 42 43 for m in self.measurements: 44 m.start(id) 45 46 func() 47 48 for m in self.measurements: 49 m.stop(id) 50 51 gc.enable() 52 53 def report(self, reporter, name): 54 """Report the measured results.""" 55 for m in self.measurements: 56 m.report(reporter, name) 57 58class Measurement(object): 59 """A measurement for a certain aspect.""" 60 61 def __init__(self, name, result): 62 """Constructor of Measurement. 63 64 Attribute result is the TestResult associated with measurement. 65 """ 66 self.name = name; 67 self.result = result 68 69 def start(self, id): 70 """Abstract method to start the measurement.""" 71 raise NotImplementedError("Abstract Method:start") 72 73 def stop(self, id): 74 """Abstract method to stop the measurement. 75 76 When the measurement is stopped, we've got something, and 77 record them in result. 78 """ 79 raise NotImplementedError("Abstract Method:stop.") 80 81 def report(self, reporter, name): 82 """Report the measured data by argument reporter.""" 83 self.result.report(reporter, name + " " + self.name) 84 85class MeasurementCpuTime(Measurement): 86 """Measurement on CPU time.""" 87 # On UNIX, time.clock() measures the amount of CPU time that has 88 # been used by the current process. On Windows it will measure 89 # wall-clock seconds elapsed since the first call to the function. 90 # Something other than time.clock() should be used to measure CPU 91 # time on Windows. 92 93 def __init__(self, result): 94 super(MeasurementCpuTime, self).__init__("cpu_time", result) 95 self.start_time = 0 96 97 def start(self, id): 98 self.start_time = time.clock() 99 100 def stop(self, id): 101 if os.name == 'nt': 102 cpu_time = 0 103 else: 104 cpu_time = time.clock() - self.start_time 105 self.result.record (id, cpu_time) 106 107class MeasurementWallTime(Measurement): 108 """Measurement on Wall time.""" 109 110 def __init__(self, result): 111 super(MeasurementWallTime, self).__init__("wall_time", result) 112 self.start_time = 0 113 114 def start(self, id): 115 self.start_time = time.time() 116 117 def stop(self, id): 118 wall_time = time.time() - self.start_time 119 self.result.record (id, wall_time) 120 121class MeasurementVmSize(Measurement): 122 """Measurement on memory usage represented by VmSize.""" 123 124 def __init__(self, result): 125 super(MeasurementVmSize, self).__init__("vmsize", result) 126 127 def _compute_process_memory_usage(self, key): 128 file_path = "/proc/%d/status" % os.getpid() 129 try: 130 t = open(file_path) 131 v = t.read() 132 t.close() 133 except: 134 return 0 135 i = v.index(key) 136 v = v[i:].split(None, 3) 137 if len(v) < 3: 138 return 0 139 return int(v[1]) 140 141 def start(self, id): 142 pass 143 144 def stop(self, id): 145 memory_used = self._compute_process_memory_usage("VmSize:") 146 self.result.record (id, memory_used) 147