Skip to content

Commit f23948c

Browse files
committed
refactor(macrobenchmark): Collect log chunks per file
Chunks were merged across every *.log found, so two devices each emitting the same number of chunks would overwrite each other's indices and reassemble into one bogus document. Collect per file and report when more than one log carries results, which also drops the cross-file total comparison that was standing in for this check. Build the summary table and per-iteration details in one pass while here.
1 parent c212da5 commit f23948c

1 file changed

Lines changed: 39 additions & 33 deletions

File tree

‎scripts/parse-macrobenchmark-log.py‎

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,14 @@ def log_messages(log_file):
3939
yield line
4040

4141

42-
def collect_chunks(log_files):
43-
"""Returns the chunk texts keyed by index, plus the expected total."""
44-
chunks = {}
45-
total = None
46-
for log_file in log_files:
47-
for message in log_messages(log_file):
48-
match = CHUNK_RE.search(message)
49-
if not match:
50-
continue
51-
index, chunk_total, text = int(match.group(1)), int(match.group(2)), match.group(3)
52-
if total is not None and chunk_total != total:
53-
sys.exit(
54-
f"Found chunks from more than one benchmark run "
55-
f"(totals {total} and {chunk_total}) in {log_file}"
56-
)
57-
total = chunk_total
58-
chunks[index] = text
42+
def collect_chunks(log_file):
43+
"""Returns one log's chunk texts keyed by index, plus the expected total."""
44+
chunks, total = {}, None
45+
for message in log_messages(log_file):
46+
match = CHUNK_RE.search(message)
47+
if match:
48+
index, total = int(match.group(1)), int(match.group(2))
49+
chunks[index] = match.group(3)
5950
return chunks, total
6051

6152

@@ -86,25 +77,30 @@ def format_summary(data):
8677
"",
8778
]
8879

89-
lines += ["| Benchmark | Metric | min | median | max | CoV | iterations |", "|---|---|--:|--:|--:|--:|--:|"]
80+
table = [
81+
"| Benchmark | Metric | min | median | max | CoV | iterations |",
82+
"|---|---|--:|--:|--:|--:|--:|",
83+
]
84+
details = []
9085
for benchmark in data["benchmarks"]:
86+
name = f"{benchmark['className'].rsplit('.', 1)[-1]}.{benchmark['name']}"
9187
for metric, result in sorted(benchmark["metrics"].items()):
92-
lines.append(
93-
f"| `{benchmark['className'].rsplit('.', 1)[-1]}.{benchmark['name']}` "
94-
f"| {metric} "
95-
f"| {result['minimum']:.1f} "
96-
f"| {result['median']:.1f} "
97-
f"| {result['maximum']:.1f} "
98-
f"| {result['coefficientOfVariation'] * 100:.1f}% "
99-
f"| {len(result['runs'])} |"
88+
table.append(
89+
f"| `{name}` | {metric} "
90+
f"| {result['minimum']:.1f} | {result['median']:.1f} | {result['maximum']:.1f} "
91+
f"| {result['coefficientOfVariation'] * 100:.1f}% | {len(result['runs'])} |"
10092
)
101-
102-
for benchmark in data["benchmarks"]:
103-
for metric, result in sorted(benchmark["metrics"].items()):
10493
runs = ", ".join(f"{run:.1f}" for run in result["runs"])
105-
lines += ["", f"<details><summary>{metric} per iteration</summary>", "", runs, "", "</details>"]
94+
details += [
95+
"",
96+
f"<details><summary>{metric} per iteration</summary>",
97+
"",
98+
runs,
99+
"",
100+
"</details>",
101+
]
106102

107-
return "\n".join(lines)
103+
return "\n".join(lines + table + details)
108104

109105

110106
def main():
@@ -117,12 +113,22 @@ def main():
117113
if not log_files:
118114
sys.exit(f"No *.log files under {args.artifacts_dir}")
119115

120-
chunks, total = collect_chunks(log_files)
121-
if total is None:
116+
# Keyed by file so chunks from two devices can never be merged into one bogus document.
117+
per_log = {log: collect_chunks(log) for log in log_files}
118+
with_chunks = {log: result for log, (result, total) in per_log.items() if total}
119+
if not with_chunks:
122120
sys.exit(
123121
"No SentryBenchmarkData chunks in the device log. The benchmark most likely "
124122
"failed before reporting — check junit.xml and the log for Macrobenchmark errors."
125123
)
124+
if len(with_chunks) > 1:
125+
sys.exit(
126+
"Chunks from more than one run: "
127+
+ ", ".join(str(log) for log in with_chunks)
128+
+ ". This parser reports a single device."
129+
)
130+
log_file = next(iter(with_chunks))
131+
chunks, total = per_log[log_file]
126132

127133
data = json.loads(reassemble(chunks, total))
128134

0 commit comments

Comments
 (0)