Commit | Line | Data |
---|---|---|
88b9d363 | 1 | # Copyright (C) 2013-2022 Free Software Foundation, Inc. |
f27a1236 YQ |
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 | ||
16 | import time | |
17 | import os | |
18 | import gc | |
19 | ||
13123da8 | 20 | |
f27a1236 YQ |
21 | class Measure(object): |
22 | """A class that measure and collect the interesting data for a given testcase. | |
23 | ||
24 | An instance of Measure has a collection of measurements, and each | |
25 | of them is to measure a given aspect, such as time and memory. | |
26 | """ | |
27 | ||
28 | def __init__(self, measurements): | |
29 | """Constructor of measure. | |
30 | ||
31 | measurements is a collection of Measurement objects. | |
32 | """ | |
33 | ||
34 | self.measurements = measurements | |
35 | ||
36 | def measure(self, func, id): | |
37 | """Measure the operations done by func with a collection of measurements.""" | |
38 | # Enable GC, force GC and disable GC before running test in order to reduce | |
39 | # the interference from GC. | |
40 | gc.enable() | |
41 | gc.collect() | |
42 | gc.disable() | |
43 | ||
44 | for m in self.measurements: | |
45 | m.start(id) | |
46 | ||
47 | func() | |
48 | ||
49 | for m in self.measurements: | |
50 | m.stop(id) | |
51 | ||
52 | gc.enable() | |
53 | ||
54 | def report(self, reporter, name): | |
55 | """Report the measured results.""" | |
56 | for m in self.measurements: | |
57 | m.report(reporter, name) | |
58 | ||
13123da8 | 59 | |
f27a1236 YQ |
60 | class Measurement(object): |
61 | """A measurement for a certain aspect.""" | |
62 | ||
63 | def __init__(self, name, result): | |
64 | """Constructor of Measurement. | |
65 | ||
66 | Attribute result is the TestResult associated with measurement. | |
67 | """ | |
13123da8 | 68 | self.name = name |
f27a1236 YQ |
69 | self.result = result |
70 | ||
71 | def start(self, id): | |
72 | """Abstract method to start the measurement.""" | |
73 | raise NotImplementedError("Abstract Method:start") | |
74 | ||
75 | def stop(self, id): | |
76 | """Abstract method to stop the measurement. | |
77 | ||
78 | When the measurement is stopped, we've got something, and | |
79 | record them in result. | |
80 | """ | |
81 | raise NotImplementedError("Abstract Method:stop.") | |
82 | ||
83 | def report(self, reporter, name): | |
84 | """Report the measured data by argument reporter.""" | |
85 | self.result.report(reporter, name + " " + self.name) | |
86 | ||
13123da8 | 87 | |
f27a1236 YQ |
88 | class MeasurementCpuTime(Measurement): |
89 | """Measurement on CPU time.""" | |
13123da8 | 90 | |
f27a1236 YQ |
91 | # On UNIX, time.clock() measures the amount of CPU time that has |
92 | # been used by the current process. On Windows it will measure | |
93 | # wall-clock seconds elapsed since the first call to the function. | |
94 | # Something other than time.clock() should be used to measure CPU | |
95 | # time on Windows. | |
96 | ||
97 | def __init__(self, result): | |
98 | super(MeasurementCpuTime, self).__init__("cpu_time", result) | |
99 | self.start_time = 0 | |
100 | ||
101 | def start(self, id): | |
102 | self.start_time = time.clock() | |
103 | ||
104 | def stop(self, id): | |
13123da8 | 105 | if os.name == "nt": |
f27a1236 YQ |
106 | cpu_time = 0 |
107 | else: | |
108 | cpu_time = time.clock() - self.start_time | |
13123da8 SM |
109 | self.result.record(id, cpu_time) |
110 | ||
f27a1236 YQ |
111 | |
112 | class MeasurementWallTime(Measurement): | |
113 | """Measurement on Wall time.""" | |
114 | ||
115 | def __init__(self, result): | |
116 | super(MeasurementWallTime, self).__init__("wall_time", result) | |
117 | self.start_time = 0 | |
118 | ||
119 | def start(self, id): | |
120 | self.start_time = time.time() | |
121 | ||
122 | def stop(self, id): | |
123 | wall_time = time.time() - self.start_time | |
13123da8 SM |
124 | self.result.record(id, wall_time) |
125 | ||
f27a1236 YQ |
126 | |
127 | class MeasurementVmSize(Measurement): | |
128 | """Measurement on memory usage represented by VmSize.""" | |
129 | ||
130 | def __init__(self, result): | |
131 | super(MeasurementVmSize, self).__init__("vmsize", result) | |
132 | ||
133 | def _compute_process_memory_usage(self, key): | |
134 | file_path = "/proc/%d/status" % os.getpid() | |
135 | try: | |
136 | t = open(file_path) | |
137 | v = t.read() | |
138 | t.close() | |
139 | except: | |
140 | return 0 | |
141 | i = v.index(key) | |
142 | v = v[i:].split(None, 3) | |
143 | if len(v) < 3: | |
144 | return 0 | |
145 | return int(v[1]) | |
146 | ||
147 | def start(self, id): | |
148 | pass | |
149 | ||
150 | def stop(self, id): | |
151 | memory_used = self._compute_process_memory_usage("VmSize:") | |
13123da8 | 152 | self.result.record(id, memory_used) |