Skip to content

Commit f0dddaa

Browse files
art049claude
andcommitted
feat: add asv-codspeed package for airspeed velocity support
Add a new `asv-codspeed` workspace package that enables running ASV (airspeed velocity) benchmarks with CodSpeed instrumentation. The package discovers `time_*` benchmarks, runs them through the existing pytest-codspeed instruments (walltime and valgrind), and reports results in the same format so the CodSpeed platform treats them identically. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent adee8a1 commit f0dddaa

15 files changed

Lines changed: 1512 additions & 3 deletions

File tree

asv-codspeed/pyproject.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[project]
2+
name = "asv-codspeed"
3+
version = "0.1.0"
4+
description = "Run ASV (airspeed velocity) benchmarks with CodSpeed instrumentation"
5+
license = "MIT"
6+
requires-python = ">=3.9"
7+
authors = [{ name = "Arthur Pastel", email = "arthur@codspeed.io" }]
8+
keywords = ["codspeed", "benchmark", "performance", "asv", "airspeed-velocity"]
9+
classifiers = [
10+
"Development Status :: 3 - Alpha",
11+
"Intended Audience :: Developers",
12+
"Programming Language :: Python :: 3",
13+
"Topic :: Software Development :: Testing",
14+
"Topic :: System :: Benchmark",
15+
]
16+
dependencies = [
17+
"pytest-codspeed>=4.2.0",
18+
"rich>=13.8.1",
19+
]
20+
21+
[project.scripts]
22+
asv-codspeed = "asv_codspeed.__main__:main"
23+
24+
[build-system]
25+
requires = ["setuptools >= 61"]
26+
build-backend = "setuptools.build_meta"
27+
28+
[tool.setuptools.packages.find]
29+
where = ["src"]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__version__ = "0.1.0"
2+
__semver_version__ = "0.1.0"
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
from __future__ import annotations
2+
3+
import argparse
4+
import sys
5+
from pathlib import Path
6+
7+
from asv_codspeed import __version__
8+
from asv_codspeed.runner import run_benchmarks
9+
10+
from pytest_codspeed.instruments import MeasurementMode
11+
12+
13+
def main(argv: list[str] | None = None) -> int:
14+
parser = argparse.ArgumentParser(
15+
prog="asv-codspeed",
16+
description="Run ASV benchmarks with CodSpeed instrumentation",
17+
)
18+
parser.add_argument(
19+
"--version",
20+
action="version",
21+
version=f"asv-codspeed {__version__}",
22+
)
23+
24+
subparsers = parser.add_subparsers(dest="command", required=True)
25+
26+
# 'run' subcommand
27+
run_parser = subparsers.add_parser("run", help="Run ASV benchmarks")
28+
run_parser.add_argument(
29+
"benchmark_dir",
30+
type=Path,
31+
nargs="?",
32+
default=Path("benchmarks"),
33+
help="Path to benchmark directory (default: benchmarks/)",
34+
)
35+
run_parser.add_argument(
36+
"--mode",
37+
choices=[m.value for m in MeasurementMode],
38+
default=None,
39+
help="Measurement mode (default: walltime locally, simulation in CI)",
40+
)
41+
run_parser.add_argument(
42+
"--warmup-time",
43+
type=float,
44+
default=None,
45+
help="Warmup time in seconds (walltime mode only)",
46+
)
47+
run_parser.add_argument(
48+
"--max-time",
49+
type=float,
50+
default=None,
51+
help="Maximum benchmark time in seconds",
52+
)
53+
run_parser.add_argument(
54+
"--max-rounds",
55+
type=int,
56+
default=None,
57+
help="Maximum number of benchmark rounds",
58+
)
59+
run_parser.add_argument(
60+
"--bench",
61+
type=str,
62+
default=None,
63+
help="Regex pattern to filter benchmarks",
64+
)
65+
66+
args = parser.parse_args(argv)
67+
68+
if args.command == "run":
69+
import os
70+
71+
# Determine mode
72+
if args.mode:
73+
mode = MeasurementMode(args.mode)
74+
elif os.environ.get("CODSPEED_ENV") is not None:
75+
if os.environ.get("CODSPEED_RUNNER_MODE") == "walltime":
76+
mode = MeasurementMode.WallTime
77+
else:
78+
mode = MeasurementMode.Simulation
79+
else:
80+
mode = MeasurementMode.WallTime
81+
82+
profile_folder = os.environ.get("CODSPEED_PROFILE_FOLDER")
83+
84+
return run_benchmarks(
85+
benchmark_dir=args.benchmark_dir,
86+
mode=mode,
87+
warmup_time=args.warmup_time,
88+
max_time=args.max_time,
89+
max_rounds=args.max_rounds,
90+
bench_filter=args.bench,
91+
profile_folder=Path(profile_folder) if profile_folder else None,
92+
)
93+
94+
return 1
95+
96+
97+
if __name__ == "__main__":
98+
sys.exit(main())

0 commit comments

Comments
 (0)