Skip to content

Commit d9fd5e4

Browse files
committed
test(benchmark): more refactoring
1 parent f84573d commit d9fd5e4

File tree

1 file changed

+102
-78
lines changed

1 file changed

+102
-78
lines changed

lab/benchmark.py

Lines changed: 102 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ def run_no_coverage(self, env):
159159
return self.run_tox(env, env.pyver.toxenv, "--skip-pkg-install")
160160

161161
def run_with_coverage(self, env, pip_args, cov_options):
162+
assert not cov_options, f"ToxProject.run_with_coverage can't take cov_options={cov_options!r}"
162163
self.run_tox(env, env.pyver.toxenv, "--notest")
163164
env.shell.run_command(
164165
f".tox/{env.pyver.toxenv}/bin/python -m pip install {pip_args}"
@@ -286,6 +287,16 @@ def __init__(self, path, slug):
286287
self.slug = slug
287288
self.toxenv = None
288289

290+
@dataclasses.dataclass
291+
class Coverage:
292+
"""A version of coverage.py to use, maybe None."""
293+
# Short word for messages, directories, etc
294+
slug: str
295+
# Arguments for "pip install ..."
296+
pip_args: Optional[str] = None
297+
# Tweaks to the .coveragerc file
298+
options: Optional[str] = None
299+
289300

290301
@dataclasses.dataclass
291302
class Env:
@@ -296,67 +307,78 @@ class Env:
296307
shell: ShellSession
297308

298309

299-
def run_experiment(
300-
py_versions: List[PyVersion],
301-
cov_versions: List[Tuple[str, Optional[str], Optional[str]]],
302-
projects: List[ProjectToTest],
303-
num_runs: int = 3,
304-
rows: Optional[List[str]] = None,
305-
column: Optional[str] = None,
306-
ratios: Iterable[Tuple[str, str, str]] = (),
307-
):
308-
"""Run test suites under different conditions."""
309-
310-
result_data: Dict[Tuple[str, str, str], float] = {}
311-
results = []
312-
for proj in projects:
313-
print(f"Testing with {proj.slug}")
314-
with ShellSession(f"output_{proj.slug}.log") as shell:
315-
proj.get_source(shell)
316-
317-
for pyver in py_versions:
318-
print(f"Making venv for {proj.slug} {pyver.slug}")
319-
venv_dir = f"venv_{proj.slug}_{pyver.slug}"
320-
shell.run_command(f"{pyver.command} -m venv {venv_dir}")
321-
python = Path.cwd() / f"{venv_dir}/bin/python"
322-
shell.run_command(f"{python} -V")
323-
env = Env(pyver, python, shell)
324-
325-
with change_dir(Path(proj.slug)):
326-
print(f"Prepping for {proj.slug} {pyver.slug}")
327-
proj.prep_environment(env)
328-
for cov_slug, cov_pip, cov_options in cov_versions:
329-
durations = []
330-
for run_num in range(num_runs):
331-
print(
332-
f"Running tests, cov={cov_slug}, {run_num+1} of {num_runs}"
310+
ResultData = Dict[Tuple[str, str, str], float]
311+
312+
class Experiment:
313+
"""A particular time experiment to run."""
314+
315+
def __init__(
316+
self,
317+
py_versions: List[PyVersion],
318+
cov_versions: List[Coverage],
319+
projects: List[ProjectToTest],
320+
):
321+
self.py_versions = py_versions
322+
self.cov_versions = cov_versions
323+
self.projects = projects
324+
self.result_data: ResultData = {}
325+
326+
def run(self, num_runs: int = 3) -> None:
327+
results = []
328+
for proj in self.projects:
329+
print(f"Testing with {proj.slug}")
330+
with ShellSession(f"output_{proj.slug}.log") as shell:
331+
proj.get_source(shell)
332+
333+
for pyver in self.py_versions:
334+
print(f"Making venv for {proj.slug} {pyver.slug}")
335+
venv_dir = f"venv_{proj.slug}_{pyver.slug}"
336+
shell.run_command(f"{pyver.command} -m venv {venv_dir}")
337+
python = Path.cwd() / f"{venv_dir}/bin/python"
338+
shell.run_command(f"{python} -V")
339+
env = Env(pyver, python, shell)
340+
341+
with change_dir(Path(proj.slug)):
342+
print(f"Prepping for {proj.slug} {pyver.slug}")
343+
proj.prep_environment(env)
344+
for cov_ver in self.cov_versions:
345+
durations = []
346+
for run_num in range(num_runs):
347+
print(
348+
f"Running tests, cov={cov_ver.slug}, {run_num+1} of {num_runs}"
349+
)
350+
if cov_ver.pip_args is None:
351+
dur = proj.run_no_coverage(env)
352+
else:
353+
dur = proj.run_with_coverage(
354+
env, cov_ver.pip_args, cov_ver.options,
355+
)
356+
print(f"Tests took {dur:.3f}s")
357+
durations.append(dur)
358+
med = statistics.median(durations)
359+
result = (
360+
f"Median for {proj.slug}, {pyver.slug}, "
361+
+ f"cov={cov_ver.slug}: {med:.3f}s"
333362
)
334-
if cov_pip is None:
335-
dur = proj.run_no_coverage(env)
336-
else:
337-
dur = proj.run_with_coverage(env, cov_pip, cov_options)
338-
print(f"Tests took {dur:.3f}s")
339-
durations.append(dur)
340-
med = statistics.median(durations)
341-
result = (
342-
f"Median for {proj.slug}, {pyver.slug}, "
343-
+ f"cov={cov_slug}: {med:.3f}s"
344-
)
345-
print(f"## {result}")
346-
results.append(result)
347-
result_key = (proj.slug, pyver.slug, cov_slug)
348-
result_data[result_key] = med
349-
350-
print("# Results")
351-
for result in results:
352-
print(result)
353-
354-
if rows:
355-
assert column
363+
print(f"## {result}")
364+
results.append(result)
365+
result_key = (proj.slug, pyver.slug, cov_ver.slug)
366+
self.result_data[result_key] = med
367+
368+
print("# Results")
369+
for result in results:
370+
print(result)
371+
372+
def show_results(
373+
self,
374+
rows: List[str],
375+
column: str,
376+
ratios: Iterable[Tuple[str, str, str]] = (),
377+
) -> None:
356378
dimensions = {
357-
"cov": [cov_slug for cov_slug, _, _ in cov_versions],
358-
"pyver": [pyver.slug for pyver in py_versions],
359-
"proj": [proj.slug for proj in projects],
379+
"cov": [cov_ver.slug for cov_ver in self.cov_versions],
380+
"pyver": [pyver.slug for pyver in self.py_versions],
381+
"proj": [proj.slug for proj in self.projects],
360382
}
361383

362384
table_axes = [dimensions[rowname] for rowname in rows]
@@ -381,12 +403,12 @@ def as_table_row(vals):
381403
for col in dimensions[column]:
382404
key = (*tup, col)
383405
key = tuple(key[i] for i in remap)
384-
result_time = result_data[key]
406+
result_time = self.result_data[key] # type: ignore
385407
row.append(f"{result_time:.3f} s")
386408
col_data[col] = result_time
387409
for _, num, denom in ratios:
388410
ratio = col_data[num] / col_data[denom]
389-
row.append(f"{ratio:.3f}")
411+
row.append(f"{int(ratio * 100):d}%")
390412
print(as_table_row(row))
391413

392414

@@ -399,16 +421,16 @@ def as_table_row(vals):
399421
with change_dir(PERF_DIR):
400422

401423
if 1:
402-
run_experiment(
424+
exp = Experiment(
403425
py_versions=[
404426
Python(3, 10),
405427
Python(3, 11),
406-
AdHocPython("/usr/local/cpython", "gh93493"),
428+
#AdHocPython("/usr/local/cpython", "gh93493"),
407429
],
408430
cov_versions=[
409-
("none", None, None),
410-
("6.4.1", "coverage==6.4.1", ""),
411-
# (
431+
Coverage("none"),
432+
Coverage("6.4.1", "coverage==6.4.1"),
433+
# Coverage(
412434
# "tip timid",
413435
# "git+https://github.com/nedbat/coveragepy.git@master",
414436
# "timid=True",
@@ -421,24 +443,26 @@ def as_table_row(vals):
421443
SlipcoverBenchmark("bm_sudoku.py"),
422444
SlipcoverBenchmark("bm_spectral_norm.py"),
423445
],
424-
num_runs=3,
446+
)
447+
exp.run(num_runs=3)
448+
exp.show_results(
425449
rows=["cov", "proj"],
426450
column="pyver",
427451
ratios=[
428452
("3.11 vs 3.10", "python3.11", "python3.10"),
429-
("fix vs 3.10", "gh93493", "python3.10"),
453+
#("fix vs 3.10", "gh93493", "python3.10"),
430454
],
431455
)
432456

433457
if 0:
434-
run_experiment(
458+
exp = Experiment(
435459
py_versions=[
436460
PyPy(3, 9),
437461
],
438462
cov_versions=[
439-
("none", None, None),
440-
("6.4", "coverage==6.4", ""),
441-
(
463+
Coverage("none", None, None),
464+
Coverage("6.4", "coverage==6.4", ""),
465+
Coverage(
442466
"PR 1381",
443467
"git+https://github.com/cfbolz/coveragepy.git@f_trace_lines",
444468
"",
@@ -447,21 +471,21 @@ def as_table_row(vals):
447471
projects=[
448472
ProjectPytestHtml(),
449473
],
450-
num_runs=3,
451474
)
475+
exp.run(num_runs=3)
452476

453477
if 0:
454-
run_experiment(
478+
exp = Experiment(
455479
py_versions=[
456480
PyPy(3, 9),
457481
],
458482
cov_versions=[
459-
("none", None, None),
460-
("6.4", "coverage", ""),
461-
("tip", "git+https://github.com/nedbat/coveragepy.git@master", ""),
483+
Coverage("none", None, None),
484+
Coverage("6.4", "coverage", ""),
485+
Coverage("tip", "git+https://github.com/nedbat/coveragepy.git@master", ""),
462486
],
463487
projects=[
464488
AdHocProject("/src/bugs/bug1339/bug1339.py"),
465489
],
466-
num_runs=7,
467490
)
491+
exp.run(num_runs=7)

0 commit comments

Comments
 (0)