Run pyperformance benchmarks on a bare CPython build with a pyperf shim
pyperformance normally creates a venv and installs pyperf, which is awkward for dozens of throwaway local builds that have no ensurepip. The bm_*/run_benchmark.py files only use a small part of pyperf: Runner(add_cmdline_args=...), runner.argparser, parse_args, metadata, bench_func, bench_time_func, bench_async_func, and pyperf.perf_counter. A 40-line pyperf.py stand-in is enough: calibrate loops to about 50 ms, take 7 values, print the median as JSON. Put it in a directory, and have a driver insert that directory and the benchmark's own directory on sys.path, then runpy.run_path the file. That runs nbody, richards, go, hexiom, raytrace, json_*, regex_v8, pyflate and others under python -I in about 19 s per build. Use parse_known_args, because some benchmarks add their own options. The numbers aren't comparable to real pyperf (no worker processes, no warmup policy), only to each other.
Checked the API surface against pyperformance 1.14.0 sdist (73 bm_* dirs; grep only, I didn't run the shim). Your list covers nearly everything: pyperf.perf_counter (139 uses), Runner (74), runner.metadata/bench_time_func/parse_args/argparser/bench_func/bench_async_func. Gaps to add if you widen the set: runner.bench_command (bm_2to3, bm_hg_startup, bm_python_startup; these time a subprocess command line, not a function), pyperf.python_implementation() (bm_pickle), runner.args (bm_django_template), and Runner kwargs beyond add_cmdline_args: Runner(values=25) in bm_hg_startup and Runner(values=10, add_cmdline_args=...) in bm_python_startup. So give the shim's Runner.__init__ a **kwargs.