-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathvalgrind.py
More file actions
93 lines (75 loc) · 3.04 KB
/
Copy pathvalgrind.py
File metadata and controls
93 lines (75 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from __future__ import annotations
import sys
from typing import TYPE_CHECKING
from pytest_codspeed import __semver_version__
from pytest_codspeed.instruments import Instrument
from pytest_codspeed.instruments.hooks import InstrumentHooks
if TYPE_CHECKING:
from typing import Any, Callable
from pytest import Session
from pytest_codspeed.instruments import P, T
from pytest_codspeed.plugin import BenchmarkMarkerOptions, CodSpeedConfig
SUPPORTS_PERF_TRAMPOLINE = sys.version_info >= (3, 12)
class ValgrindInstrument(Instrument):
instrument = "valgrind"
instrument_hooks: InstrumentHooks | None
def __init__(self, config: CodSpeedConfig) -> None:
self.benchmark_count = 0
try:
self.instrument_hooks = InstrumentHooks()
self.instrument_hooks.set_integration("pytest-codspeed", __semver_version__)
except RuntimeError:
self.instrument_hooks = None
self.should_measure = self.instrument_hooks is not None
def get_instrument_config_str_and_warns(self) -> tuple[str, list[str]]:
config = (
f"mode: instrumentation, "
f"callgraph: {'enabled' if SUPPORTS_PERF_TRAMPOLINE else 'not supported'}"
)
warnings = []
if not self.should_measure:
warnings.append(
"\033[1m"
"NOTICE: codspeed is enabled, but no performance measurement"
" will be made since it's running in an unknown environment."
"\033[0m"
)
return config, warnings
def measure(
self,
marker_options: BenchmarkMarkerOptions,
name: str,
uri: str,
fn: Callable[P, T],
*args: P.args,
**kwargs: P.kwargs,
) -> T:
self.benchmark_count += 1
if not self.instrument_hooks:
return fn(*args, **kwargs)
def __codspeed_root_frame__() -> T:
return fn(*args, **kwargs)
if SUPPORTS_PERF_TRAMPOLINE:
# Warmup CPython performance map cache
__codspeed_root_frame__()
# Manually call the library function to avoid an extra stack frame. Also
# call the callgrind markers directly to avoid extra overhead.
self.instrument_hooks.lib.callgrind_start_instrumentation()
try:
return __codspeed_root_frame__()
finally:
# Ensure instrumentation is stopped even if the test failed
self.instrument_hooks.lib.callgrind_stop_instrumentation()
self.instrument_hooks.set_executed_benchmark(uri)
def report(self, session: Session) -> None:
reporter = session.config.pluginmanager.get_plugin("terminalreporter")
count_suffix = "benchmarked" if self.should_measure else "benchmark tested"
reporter.write_sep(
"=",
f"{self.benchmark_count} {count_suffix}",
)
def get_result_dict(self) -> dict[str, Any]:
return {
"instrument": {"type": self.instrument},
# bench results will be dumped by valgrind
}