Skip to content

perf(callgrind): skip the I1 lookup for consecutive same-line instruction fetches#30

Open
codspeed-hq[bot] wants to merge 1 commit into
masterfrom
codspeed-optim-callgrind-cache-sim-skip-the-i1-lookup-for-consecu-1784951431976
Open

perf(callgrind): skip the I1 lookup for consecutive same-line instruction fetches#30
codspeed-hq[bot] wants to merge 1 commit into
masterfrom
codspeed-optim-callgrind-cache-sim-skip-the-i1-lookup-for-consecu-1784951431976

Conversation

@codspeed-hq

@codspeed-hq codspeed-hq Bot commented Jul 25, 2026

Copy link
Copy Markdown

Summary

Adds a one-entry "last instruction-cache line" fast path to cachesim_I1_ref in callgrind/sim.c, the L1 instruction-cache lookup that Callgrind runs on every simulated instruction fetch when --cache-sim=yes.

Why it helps

A 64-byte cache line holds ~16 instructions, and instructions in a basic block are fetched sequentially, so ~15 out of every 16 I-fetches land in the same cache line as the previous fetch. The baseline recomputes the set index, indexes into the tag array, and walks the associativity way-list on each of those fetches.

The fast path remembers the last I1 line touched (last_iblock). When the next single-line fetch matches it, the line is guaranteed still resident and MRU (the previous access made it so, and nothing accessed I1 in between), so the result is a guaranteed L1 hit returned immediately — skipping the whole cachesim_refcachesim_setref set/tag machinery.

Correctness

The line was already made MRU by the previous access, so not re-touching it leaves the cache state and every hit/miss counter identical. The fast-path line is invalidated on a straddling access and on cachesim_clear() (cache reset between dumps).

Verified locally:

  • Byte-for-byte identical Callgrind event counts (Ir Dr Dw I1mr D1mr D1mw ILmr DLmr DLmw) against the baseline on a deterministic workload — under the default cache config and tiny I1 caches (--I1=1024,2,64, --I1=2048,4,32) that force heavy I-cache eviction.
  • All 22 callgrind regression tests pass (including simwork-cache with --cache-sim=yes and the notpower2 variants).

Measurement

Local interleaved A/B on the full-with-inline (cache-sim) config, 8 pairs on a compute-heavy workload:

base opt improvement
median 1.271s 1.233s +3.0%

Every one of the 8 interleaved A/B pairs showed the optimized build faster (+1.8% … +3.4%). The change is minimal (one static variable + a fast-path branch) and touches only the non-writeback, non-cacheuse I1 read path.

… fetches

Add a one-entry last-instruction-cache-line fast path to cachesim_I1_ref.
Consecutive instructions in a basic block almost always land in the same
64-byte cache line (~16 instructions), so ~15 of every 16 I-fetches hit
the same line as the previous one. Remembering that line lets those
fetches return a guaranteed L1 hit without recomputing the set index or
walking the associativity way-list.

The previous access already made the line MRU, so not re-touching it
leaves the cache state and every hit/miss counter identical. The fast
path is invalidated on a straddling access and on cachesim_clear().

Verified byte-for-byte identical Callgrind event counts against the
baseline across default and tiny-I1 (--I1=1024,2,64 / --I1=2048,4,32)
configs, and all 22 callgrind regression tests pass.
@codspeed-hq
codspeed-hq Bot requested a review from not-matthias July 25, 2026 04:02
@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown

Greptile Summary

Adds a one-entry instruction-cache fast path that bypasses redundant tag lookups for consecutive same-line fetches.

  • Tracks the most recently accessed I1 cache block.
  • Preserves the existing lookup for first, changed-line, and straddling accesses.
  • Invalidates the tracked block whenever cache state is cleared.

Confidence Score: 5/5

The PR appears safe to merge, with the optimized path preserving the existing cache-state transitions and event classification.

Consecutive same-line accesses can safely return an I1 hit because the preceding access made that line resident and most-recently used; all paths that can invalidate this assumption either update the tracked block or explicitly clear it.

Important Files Changed

Filename Overview
callgrind/sim.c Adds an equivalent same-line I1 lookup shortcut with conservative invalidation on straddling accesses and cache resets; no actionable correctness issue was identified.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Instruction fetch] --> B{Single cache line?}
    B -- No --> C[Invalidate last block]
    C --> D[Run existing cache lookup]
    B -- Yes --> E{Matches last block?}
    E -- Yes --> F[Return L1 hit]
    E -- No --> G[Remember block]
    G --> H[Run I1 set lookup]
    H --> I{I1 hit?}
    D --> I
    I -- Yes --> F
    I -- No --> J[Check last-level cache]
    J --> K[Return LL hit or memory access]
Loading

Reviews (1): Last reviewed commit: "perf(callgrind): skip I1 lookup for cons..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Jul 25, 2026

Copy link
Copy Markdown
Author

Merging this PR will not alter performance

✅ 84 untouched benchmarks
⏩ 60 skipped benchmarks1


Comparing codspeed-optim-callgrind-cache-sim-skip-the-i1-lookup-for-consecu-1784951431976 (187bec1) with master (448b7d0)

Open in CodSpeed

Footnotes

  1. 60 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@codspeed-hq
codspeed-hq Bot marked this pull request as ready for review July 25, 2026 04:38
@codspeed-hq

codspeed-hq Bot commented Jul 25, 2026

Copy link
Copy Markdown
Author

Unable to generate the flame graphs

The performance report has correctly been generated, but there was an internal error while generating the flame graphs for this run. We're working on fixing the issue. Feel free to contact us on Discord or at support@codspeed.io if the issue persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant