1 # Copyright (C) 2013-2024 Free Software Foundation, Inc.
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.
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.
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/>.
21 # time.perf_counter() and time.process_time() were added in Python
22 # 3.3, time.clock() was removed in Python 3.8.
23 if sys
.version_info
< (3, 3, 0):
24 time
.perf_counter
= time
.clock
25 time
.process_time
= time
.clock
28 class Measure(object):
29 """A class that measure and collect the interesting data for a given testcase.
31 An instance of Measure has a collection of measurements, and each
32 of them is to measure a given aspect, such as time and memory.
35 def __init__(self
, measurements
):
36 """Constructor of measure.
38 measurements is a collection of Measurement objects.
41 self
.measurements
= measurements
43 def measure(self
, func
, id):
44 """Measure the operations done by func with a collection of measurements."""
45 # Enable GC, force GC and disable GC before running test in order to reduce
46 # the interference from GC.
51 for m
in self
.measurements
:
56 for m
in self
.measurements
:
61 def report(self
, reporter
, name
):
62 """Report the measured results."""
63 for m
in self
.measurements
:
64 m
.report(reporter
, name
)
67 class Measurement(object):
68 """A measurement for a certain aspect."""
70 def __init__(self
, name
, result
):
71 """Constructor of Measurement.
73 Attribute result is the TestResult associated with measurement.
79 """Abstract method to start the measurement."""
80 raise NotImplementedError("Abstract Method:start")
83 """Abstract method to stop the measurement.
85 When the measurement is stopped, we've got something, and
86 record them in result.
88 raise NotImplementedError("Abstract Method:stop.")
90 def report(self
, reporter
, name
):
91 """Report the measured data by argument reporter."""
92 self
.result
.report(reporter
, name
+ " " + self
.name
)
95 class MeasurementPerfCounter(Measurement
):
96 """Measurement on performance counter."""
98 # Measures time in fractional seconds, using a performance
99 # counter, i.e. a clock with the highest available resolution to
100 # measure a short duration. It includes time elapsed during sleep
101 # and is system-wide.
103 def __init__(self
, result
):
104 super(MeasurementPerfCounter
, self
).__init
__("perf_counter", result
)
108 self
.start_time
= time
.perf_counter()
111 perf_counter
= time
.perf_counter() - self
.start_time
112 self
.result
.record(id, perf_counter
)
115 class MeasurementProcessTime(Measurement
):
116 """Measurement on process time."""
118 # Measures the sum of the system and user CPU time of the current
119 # process. Does not include time elapsed during sleep. It is
120 # process-wide by definition.
122 def __init__(self
, result
):
123 super(MeasurementProcessTime
, self
).__init
__("process_time", result
)
127 self
.start_time
= time
.process_time()
130 process_time
= time
.process_time() - self
.start_time
131 self
.result
.record(id, process_time
)
134 class MeasurementWallTime(Measurement
):
135 """Measurement on Wall time."""
137 def __init__(self
, result
):
138 super(MeasurementWallTime
, self
).__init
__("wall_time", result
)
142 self
.start_time
= time
.time()
145 wall_time
= time
.time() - self
.start_time
146 self
.result
.record(id, wall_time
)
149 class MeasurementVmSize(Measurement
):
150 """Measurement on memory usage represented by VmSize."""
152 def __init__(self
, result
):
153 super(MeasurementVmSize
, self
).__init
__("vmsize", result
)
155 def _compute_process_memory_usage(self
, key
):
156 file_path
= "/proc/%d/status" % os
.getpid()
164 v
= v
[i
:].split(None, 3)
173 memory_used
= self
._compute
_process
_memory
_usage
("VmSize:")
174 self
.result
.record(id, memory_used
)