Repository navigation
Design write-up with overhead measurements - #8
Conversation
docs/design.md records the core contracts, the suppression and immortality rationale, the backend and emitter trade-offs, measured per-event costs, and stated limits. bench/overhead_bench measures the scope macro and compiler instrumentation against untraced twins of the same work. Closes #4 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| // Total calls made by the recursive fib: 2 * fib(n + 1) - 1. | ||
| long fib_call_count(int n) { | ||
| long a = 0; | ||
| long b = 1; |
There was a problem hiding this comment.
Logic error: loop iterates one too many times, returning 2*fib(n+2)-1 instead of 2*fib(n+1)-1.
Starting from (a=0, b=1) = (fib(0), fib(1)), each iteration advances by one Fibonacci step. After n+1 iterations b = fib(n+2), so fib_call_count returns 2*fib(n+2)-1 — not the 2*fib(n+1)-1 stated in the comment (which is the correct total-call formula).
Concrete impact for fib_n=26:
- Actual calls
T(26) = 2*fib(27)−1 = 392,835 fib_call_count(26)returns2*fib(28)−1 = 635,621(~1.618× too high)measure_instrumentationdivides by this inflated count, so the printedns/callis ~39% lower than the true per-call overheaddocs/design.mdreports "635,621 calls" which propagates this error into the published numbers
| long b = 1; | |
| for (int i = 0; i < n; ++i) { |
With i < n the loop runs n iterations, giving b = fib(n+1) and the correct return value 2*fib(n+1)-1.
Review summaryOne substantive issue found; everything else looks good. Bug:
|
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Finding applied and re-measured: the loop now computes fib(n+1) as stated, the call count for fib(26) is 392,835, and the honest per-call figure is 136.4 ns rather than the understated 86. The corrected doc notes what the corrected numbers show: both paths cost the same per event because the shared record path dominates. Single finding; merging on green. 🤖 Generated with Claude Code |
Summary
Closes the cyclescope build-out: docs/design.md with the trade-off rationale behind every load-bearing decision, plus bench/overhead_bench producing the measured numbers the doc cites.
Closes #4
Changes
docs/design.md: per-thread buffer contracts, the suppression-flag design (the ODR self-deadlock and unoptimized-recursion hazards and how the guard closes them), teardown immortality, backend and emitter choices, measured overhead with repro commands, stated limitsbench/overhead_bench.cpp+ instrumented fib twin: scope-macro cost vs empty loop, hook cost vs plain fib, divergence-checkedCYCLESCOPE_BUILD_BENCH(default ON, non-MSVC)Measured (arm64 macOS, 8 logical cores, Apple clang, Release)
Scope macro 136 ns/event (1M scopes); compiler instrumentation 86 ns/call (fib(26), 635,621 calls). Framed in the doc as one machine, one data point, with the granularity guidance that follows.
Test plan
🤖 Generated with Claude Code