Skip to content

Commit a134fbb

Browse files
authored
Merge pull request #160 from faster-cpython/display-output-url
Display output URL on summary page
2 parents 81e95d2 + 4983bd1 commit a134fbb

File tree

2 files changed

+117
-87
lines changed

2 files changed

+117
-87
lines changed

Diff for: bench_runner/scripts/generate_results.py

+116-86
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import datetime
77
import io
88
import multiprocessing
9+
import os
910
from pathlib import Path
1011
import sys
1112
from typing import Iterable, Optional, TextIO
@@ -16,7 +17,6 @@
1617
from bench_runner import plot
1718
from bench_runner.result import (
1819
load_all_results,
19-
BenchmarkComparison,
2020
Comparison,
2121
Result,
2222
)
@@ -43,100 +43,118 @@ def recurse(entry: tuple, d: dict):
4343
return d
4444

4545

46-
def write_markdown_results(filename: Path, compare: BenchmarkComparison) -> None:
47-
if filename.exists():
48-
filename.unlink()
49-
compare = compare.copy()
50-
51-
contents = compare.contents
52-
if contents is None:
53-
return
54-
55-
entries = [
56-
("fork", unquote(compare.head.fork)),
57-
("ref", compare.head.ref),
58-
("machine", f"{compare.head.system}-{compare.head.machine}"),
59-
("commit hash", compare.head.cpython_hash),
60-
("commit date", compare.head.commit_date),
61-
("overall geometric mean", compare.geometric_mean),
62-
("HPT reliability", compare.hpt_reliability),
63-
("HPT 99th percentile", compare.hpt_percentile(99)),
64-
]
46+
class ResultWriter:
47+
@staticmethod
48+
def need_to_generate(compare: Comparison) -> bool:
49+
return False
50+
51+
@staticmethod
52+
def generate(filename: Path, compare) -> None:
53+
pass
54+
55+
56+
class MarkdownResultWriter(ResultWriter):
57+
@staticmethod
58+
def need_to_generate(compare: Comparison) -> bool:
59+
return compare.contents is not None
60+
61+
@staticmethod
62+
def generate(filename: Path, compare) -> None:
63+
if filename.exists():
64+
filename.unlink()
65+
compare = compare.copy()
66+
67+
entries = [
68+
("fork", unquote(compare.head.fork)),
69+
("ref", compare.head.ref),
70+
("machine", f"{compare.head.system}-{compare.head.machine}"),
71+
("commit hash", compare.head.cpython_hash),
72+
("commit date", compare.head.commit_date),
73+
("overall geometric mean", compare.geometric_mean),
74+
("HPT reliability", compare.hpt_reliability),
75+
("HPT 99th percentile", compare.hpt_percentile(99)),
76+
]
77+
78+
if compare.memory_change is not None:
79+
entries.append(("Memory change", compare.memory_change))
80+
81+
with open(filename, "w") as fd:
82+
fd.write(f"# Results vs. {compare.base}\n\n")
83+
for key, val in entries:
84+
fd.write(f"- {key}: {val}\n")
85+
fd.write("\n")
86+
fd.write(compare.contents or "")
87+
88+
89+
class TimePlotResultWriter(ResultWriter):
90+
@staticmethod
91+
def need_to_generate(compare: Comparison) -> bool:
92+
return True
93+
94+
@staticmethod
95+
def generate(filename: Path, compare) -> None:
96+
plot.plot_diff(
97+
compare.get_timing_diff(),
98+
filename,
99+
(
100+
"Timings of "
101+
f"{unquote(compare.head.fork)}-{compare.head.ref}-"
102+
f"{compare.head.cpython_hash}"
103+
f" vs. {compare.ref.version}"
104+
),
105+
("slower", "faster"),
106+
)
65107

66-
if compare.memory_change is not None:
67-
entries.append(("Memory change", compare.memory_change))
68-
69-
with open(filename, "w") as fd:
70-
fd.write(f"# Results vs. {compare.base}\n\n")
71-
for key, val in entries:
72-
fd.write(f"- {key}: {val}\n")
73-
fd.write("\n")
74-
fd.write(contents)
75-
76-
77-
def write_time_plot_results(filename: Path, compare: BenchmarkComparison) -> None:
78-
plot.plot_diff(
79-
compare.get_timing_diff(),
80-
filename,
81-
(
82-
"Timings of "
83-
f"{unquote(compare.head.fork)}-{compare.head.ref}-"
84-
f"{compare.head.cpython_hash}"
85-
f" vs. {compare.ref.version}"
86-
),
87-
("slower", "faster"),
88-
)
89108

109+
class MemoryPlotResultWriter(ResultWriter):
110+
@staticmethod
111+
def need_to_generate(compare: Comparison) -> bool:
112+
return compare.head.system != "windows" and compare.base == "base"
90113

91-
def write_memory_plot_results(filename: Path, compare: BenchmarkComparison) -> None:
92-
if compare.head.system == "windows":
93-
# Windows doesn't have memory data
94-
return
95-
96-
if compare.base != "base":
97-
# Only generate the graphs for base comparisons
98-
return
99-
100-
plot.plot_diff(
101-
compare.get_memory_diff(),
102-
filename,
103-
(
104-
"Memory usage of "
105-
f"{unquote(compare.head.fork)}-{compare.head.ref}-"
106-
f"{compare.head.cpython_hash}"
107-
f" vs. {compare.ref.version}"
108-
),
109-
("less", "more"),
110-
)
114+
@staticmethod
115+
def generate(filename: Path, compare) -> None:
116+
plot.plot_diff(
117+
compare.get_memory_diff(),
118+
filename,
119+
(
120+
"Memory usage of "
121+
f"{unquote(compare.head.fork)}-{compare.head.ref}-"
122+
f"{compare.head.cpython_hash}"
123+
f" vs. {compare.ref.version}"
124+
),
125+
("less", "more"),
126+
)
111127

112128

113-
def write_pystats_diff(filename: Path, compare: Comparison) -> None:
114-
if filename.exists():
115-
filename.unlink()
116-
compare = compare.copy()
129+
class PystatsDiffResultWriter(ResultWriter):
130+
@staticmethod
131+
def need_to_generate(compare: Comparison) -> bool:
132+
return compare.contents is not None
117133

118-
contents = compare.contents
119-
if contents is None:
120-
return
134+
@staticmethod
135+
def generate(filename: Path, compare) -> None:
136+
if filename.exists():
137+
filename.unlink()
138+
compare = compare.copy()
121139

122-
with open(filename, "w") as fd:
123-
fd.write(contents)
140+
with open(filename, "w") as fd:
141+
fd.write(compare.contents or "")
124142

125143

126144
RESULT_TYPES = {
127145
"raw results": {
128-
".md": write_markdown_results,
129-
".png": write_time_plot_results,
130-
"-mem.png": write_memory_plot_results,
146+
".md": MarkdownResultWriter,
147+
".png": TimePlotResultWriter,
148+
"-mem.png": MemoryPlotResultWriter,
131149
},
132-
"pystats raw": {".md": write_pystats_diff},
150+
"pystats raw": {".md": PystatsDiffResultWriter},
133151
None: {},
134152
}
135153

136154

137-
def _worker(args):
138-
func, output_filename, compare = args
139-
func(output_filename, compare)
155+
def _worker(args) -> None:
156+
writer, output_filename, compare = args
157+
writer.generate(output_filename, compare)
140158

141159

142160
def save_generated_results(results: Iterable[Result], force: bool = False) -> None:
@@ -147,19 +165,31 @@ def save_generated_results(results: Iterable[Result], force: bool = False) -> No
147165
regeneration, pass ``force=True``.
148166
"""
149167
work = []
168+
directories_affected = set()
150169
for result in results:
151170
for compare in result.bases.values():
152171
if compare.filename is not None:
153-
for suffix, func in RESULT_TYPES[result.result_info[0]].items():
172+
for suffix, writer in RESULT_TYPES[result.result_info[0]].items():
154173
filename = compare.filename.parent / (
155174
compare.filename.stem + suffix
156175
)
157-
if not filename.exists() or force: # or suffix == ".png":
158-
work.append((func, filename, compare))
159-
160-
pool = multiprocessing.Pool()
161-
for i, _ in enumerate(pool.imap_unordered(_worker, work)):
162-
print(f"{i:04d}/{len(work):04d}", end="\r")
176+
if writer.need_to_generate(compare) and (
177+
not filename.exists() or force
178+
):
179+
work.append((writer, filename, compare))
180+
directories_affected.add(filename.parent)
181+
182+
with multiprocessing.Pool() as pool:
183+
for i, _ in enumerate(pool.imap_unordered(_worker, work)):
184+
print(f"{i + 1:04d}/{len(work):04d}", end="\r")
185+
print()
186+
187+
github_repo = os.environ.get("GITHUB_REPOSITORY", "UNKNOWN")
188+
for directory in directories_affected:
189+
print(
190+
"::notice ::New results at "
191+
f"https://github.com/{github_repo}_public/tree/main/{directory}"
192+
)
163193

164194

165195
def output_results_index(

Diff for: bench_runner/templates/_generate.src.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,5 @@ jobs:
5050
uses: EndBug/add-and-commit@v9
5151
if: ${{ !inputs.dry_run }}
5252
with:
53-
add: "['results', 'README.md', 'RESULTS.md', 'longitudinal.png', 'longitudinal.json', 'profiling/profiling.png', 'profiling/profiling.md', 'configs.png', 'configs.json', 'memory_long.png', 'memory_long.json', 'memory_configs.png', 'memory_configs.json']"
53+
add: "['results', 'README.md', 'RESULTS.md', 'longitudinal.png', 'longitudinal.json', 'configs.png', 'configs.json', 'memory_long.png', 'memory_long.json', 'memory_configs.png', 'memory_configs.json']"
5454
message: Benchmarking results for @${{ github.actor }}

0 commit comments

Comments
 (0)