Skip to content

Commit c66b399

Browse files
committed
docs(agents): propose macOS-only fib benchmark for flamegraph testing
1 parent 7e2bf14 commit c66b399

1 file changed

Lines changed: 109 additions & 0 deletions

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Proposal: macOS-only Fib benchmark for flamegraph testing
2+
3+
## Goal
4+
5+
Add a benchmark whose only purpose is to exercise CodSpeed's flamegraph
6+
symbolization pipeline on macOS (codspeed-macro runners). It should:
7+
8+
- run on macOS (locally and on `codspeed-macro` CI)
9+
- be **skipped** on Linux + Windows so it doesn't pollute the regular walltime
10+
results or fail on platforms where the flamegraph path isn't applicable
11+
- have a stack shape that produces an obviously-recognisable flamegraph (deep
12+
recursion = `fib`)
13+
14+
## Findings
15+
16+
- `examples/example-gradle/src/jmh/java/bench/FibBenchmark.java` already
17+
defines a recursive `fib(30)` benchmark. Reusing the same shape (but a
18+
dedicated class) keeps the flamegraph trivially recognisable.
19+
- The Gradle JMH plugin (`me.champeau.jmh` v0.7.2) exposes `includes` /
20+
`excludes` regex filters. We're already using `includes` to curate the CI
21+
subset in `examples/example-gradle/build.gradle.kts:32`.
22+
- CI is matrixed in `.github/workflows/ci.yml`. The flamegraph-relevant job
23+
is `walltime-benchmarks` on `codspeed-macro` — macOS-only by definition.
24+
The cross-platform jobs (`build-and-run-gradle`, `build-and-run-maven`) run
25+
the JMH JAR on Linux + Windows + macOS, so a naive new benchmark would also
26+
execute there.
27+
- JMH itself has no `@SkipOnPlatform`-style annotation. The two reasonable
28+
gating mechanisms are:
29+
1. Filter at the runner level (Gradle `excludes`)
30+
2. Throw / `Assume.assumeTrue(...)` inside `@Setup` (JMH treats a thrown
31+
exception in setup as a benchmark error, not a skip — so this is
32+
**not** suitable).
33+
34+
## Options
35+
36+
### 1. Gate via Gradle `excludes` based on `OperatingSystem` (recommended)
37+
38+
Add `FibFlamegraphBenchmark` next to the existing `FibBenchmark`, and in
39+
`examples/example-gradle/build.gradle.kts` exclude it everywhere except macOS:
40+
41+
```kotlin
42+
import org.gradle.internal.os.OperatingSystem
43+
44+
jmh {
45+
// …existing config…
46+
if (!OperatingSystem.current().isMacOsX) {
47+
excludes.add(".*FibFlamegraphBenchmark.*")
48+
}
49+
}
50+
```
51+
52+
The `CODSPEED_ENV` branch already filters down to a curated set on CI; add
53+
`FibFlamegraphBenchmark` to that alternation so it runs on `codspeed-macro`
54+
but stays out of the way on the regular Linux/Windows matrix.
55+
56+
Pros:
57+
- One source of truth (the build script). No per-benchmark scaffolding.
58+
- `OperatingSystem.current()` is the same API Gradle uses internally and
59+
doesn't require a new dependency.
60+
- Easy to mirror in the Maven example (`<profile><activation><os>` block).
61+
62+
Cons:
63+
- Excludes are regex-based; the benchmark class name must stay matchable.
64+
Mitigation: keep `Flamegraph` in the class name and exclude on that token.
65+
66+
### 2. Put macOS-only benchmarks in a dedicated package + filter
67+
68+
E.g. `bench.macos.FibFlamegraphBenchmark`, then exclude `bench\\.macos\\..*`
69+
when `!isMacOsX`.
70+
71+
Pros: groups future macOS-only benchmarks naturally; no per-class regex.
72+
Cons: more moving parts up front for a single benchmark.
73+
74+
### 3. Use a System property check + early `return`
75+
76+
Make the benchmark body a no-op on non-macOS. JMH still runs it, so the run
77+
shows up in results as a near-zero benchmark.
78+
79+
Pros: no build-script changes.
80+
Cons: pollutes results, defeats the "skip on Linux" goal. **Rejected.**
81+
82+
## Recommendation
83+
84+
Go with **Option 1**. Smallest diff, no new package, and the gating lives in
85+
the same place as the existing `CODSPEED_ENV` filter so future readers
86+
discover it immediately.
87+
88+
### Concrete change set (not yet applied)
89+
90+
1. New file `examples/example-gradle/src/jmh/java/bench/FibFlamegraphBenchmark.java`
91+
— copy of `FibBenchmark` with a distinct class name and a `@Param` value
92+
that pushes recursion deep enough to be visually interesting in the
93+
flamegraph (e.g. `35`).
94+
2. Edit `examples/example-gradle/build.gradle.kts`:
95+
- import `org.gradle.internal.os.OperatingSystem`
96+
- add `excludes.add(".*FibFlamegraphBenchmark.*")` under
97+
`if (!OperatingSystem.current().isMacOsX)`
98+
- extend the `CODSPEED_ENV` include alternation to include
99+
`FibFlamegraphBenchmark`
100+
3. No CI changes needed: the existing `walltime-benchmarks` job on
101+
`codspeed-macro` will pick it up automatically.
102+
103+
## Open questions
104+
105+
- Should the Maven example mirror this? The Maven example doesn't currently
106+
run under `codspeed-macro`, so probably no — but worth confirming.
107+
- Do we want to lock the `@Fork` / iteration counts down for the flamegraph
108+
benchmark specifically (a single long iteration produces a cleaner
109+
flamegraph than many short ones)?

0 commit comments

Comments
 (0)