Skip to content

Eval: Prefetch better#6555

Merged
jannotti merged 19 commits intoalgorand:masterfrom
jannotti:prefetch-better
Mar 10, 2026
Merged

Eval: Prefetch better#6555
jannotti merged 19 commits intoalgorand:masterfrom
jannotti:prefetch-better

Conversation

@jannotti
Copy link
Copy Markdown
Contributor

@jannotti jannotti commented Feb 11, 2026

Summary

This PR improves prefetching in several ways:

  1. Perform prefetching of boxes. It seems fair to assume that BoxRefs are "precise" in the sense that they are unlikely to be included and not referenced, so it's a win to get them prefetched.
  2. Begin prefetching ForeignApps. Previously we did not fetch anything from Accounts, ForeignApps, and ForeignAssets because it's not really known if those resources will be fetched at evaluation time or, for example, a holding made available by an account and an asset would be fetched, but not the account and asset params. Upon further consideration, it seems very likely that any included app is fetched. The only other reason to include it would be to fetch locals for that app and one of the accounts. But locals are less commonly used these days, global access or invoking the app in an inner txn seem much more likely. So we prefetch.
  3. Perform prefetching on the new access list. We can be a bit more precise here. Boxes and apps are fetched, as well as any locals or holdings. Since locals and holdings are explicit in tx.Access, they are almost surely needed. We also fetch any account or asset that is not used in a holding/local cross-product. There would be no reason to include them if not used in that way.
  4. We no longer bother to track all of the groups that care about a resource. It's only important to ensure that the first such group waits for the preloading of the resource. It doesn't matter that the returned resources of later groups with the same need don't explicitly include it in their returned resources.

Test Plan

@jannotti jannotti self-assigned this Feb 11, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 11, 2026

Codecov Report

❌ Patch coverage is 88.52459% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.91%. Comparing base (8d84b18) to head (1d95ca7).
⚠️ Report is 5 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
ledger/eval/prefetcher/prefetcher.go 90.39% 11 Missing and 6 partials ⚠️
util/pagedqueue.go 87.93% 3 Missing and 4 partials ⚠️
ledger/eval/eval.go 40.00% 2 Missing and 1 partial ⚠️
ledger/acctupdates.go 50.00% 0 Missing and 1 partial ⚠️

❗ There is a different number of reports uploaded between BASE (8d84b18) and HEAD (1d95ca7). Click for more details.

HEAD has 4 uploads less than BASE
Flag BASE (8d84b18) HEAD (1d95ca7)
full_coverage 4 0
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #6555       +/-   ##
===========================================
- Coverage   63.60%   47.91%   -15.69%     
===========================================
  Files         486      646      +160     
  Lines       67806    88326    +20520     
===========================================
- Hits        43125    42321      -804     
- Misses      21188    43215    +22027     
+ Partials     3493     2790      -703     
Flag Coverage Δ
full_coverage ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment thread ledger/eval/prefetcher/prefetcher.go
@jannotti jannotti marked this pull request as ready for review February 12, 2026 11:34
Copy link
Copy Markdown
Contributor

@algorandskiy algorandskiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish boxes/foreign apps were added and refactored as a consequent PR (or another way around) to simplify the review.

Comment thread ledger/lruaccts.go
Comment thread ledger/eval/prefetcher/prefetcher.go
Comment thread ledger/eval/prefetcher/prefetcher.go
Copy link
Copy Markdown
Contributor

@algorandskiy algorandskiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks correct.
Requesting one fix here

app = stxn.Txn.ForeignApps[br.Index-1]

Comment thread ledger/eval/prefetcher/prefetcher.go
Comment thread ledger/eval/prefetcher/prefetcher.go
Comment thread ledger/eval/prefetcher/prefetcher.go Outdated
algorandskiy
algorandskiy previously approved these changes Feb 23, 2026
@algorandskiy algorandskiy requested a review from cce February 23, 2026 17:40
@jannotti jannotti requested a review from gmalouf February 27, 2026 08:18
Comment thread ledger/eval/prefetcher/prefetcher.go
@gmalouf
Copy link
Copy Markdown
Contributor

gmalouf commented Mar 5, 2026

Ran through an LLM locally, found a potential sizing bug in the prefetch queue capacity math; I think allocating more space as in the first suggested fix probably is the way to handle this:

  1. Blocker: prefetch queue can panic on valid tx.Access workloads
    • In prefetcher.go:305, maxTxnGroupEntries is capped by MaxAppTotalTxnReferences (8 in V41/Future), but
      tx.Access allows up to MaxAppAccess (16).
    • The queue only expands after a group is fully processed (prefetcher.go:474), so a single group can
      enqueue more tasks than reserved and hit out-of-bounds in enqueue at line 190:190.
    • LLM reproduced this locally with non-empty groups (go run /tmp/repro6555_overflow_realistic.go), and it
      panics with:
      • panic: runtime error: index out of range [486] with length 486
      • stack points to ledger/eval/prefetcher/prefetcher.go:190 via addAccountTask.
    • Panic repro above fails consistently.

Suggested fix direction

  1. Size per-group upper bound using max(MaxAppTotalTxnReferences, MaxAppAccess) (and legacy non-app bound), or
  2. Make enqueue/task-add path capacity-safe mid-group (expand before overflow), not only at group boundaries.
  3. Add a regression test with tx.Access-heavy groups to guard this path.

@jannotti
Copy link
Copy Markdown
Contributor Author

jannotti commented Mar 5, 2026

Suggested fix direction

  1. Size per-group upper bound using max(MaxAppTotalTxnReferences, MaxAppAccess) (and legacy non-app bound), or
  2. Make enqueue/task-add path capacity-safe mid-group (expand before overflow), not only at group boundaries.
  3. Add a regression test with tx.Access-heavy groups to guard this path.

Agreed, excellent catch, Gemini. 1 is easy and I'll do that unless 2 turns out to be relatively easy too. I prefer 2, since it's futureproof, and doesn't waste space.

@jannotti
Copy link
Copy Markdown
Contributor Author

jannotti commented Mar 5, 2026

I did it the "hard" way, but I think it's much nicer to not care about a max number of resources per group.
a767bae

I ran benchmarks to make sure there was no regression

@jannotti jannotti force-pushed the prefetch-better branch 2 times, most recently from c7d6611 to c4e81e8 Compare March 5, 2026 20:50
@jannotti jannotti requested a review from algorandskiy March 5, 2026 21:16
Copy link
Copy Markdown
Contributor

@algorandskiy algorandskiy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the refactoring, incl used vs 'len/cap` thing - one less thing to track, one less bug

Comment thread ledger/eval/prefetcher/prefetcher.go
algorandskiy
algorandskiy previously approved these changes Mar 6, 2026
gmalouf
gmalouf previously approved these changes Mar 6, 2026
Comment thread ledger/eval/eval.go Outdated
Comment thread ledger/eval/prefetcher/prefetcher_test.go
Comment thread ledger/eval/prefetcher/prefetcher.go Outdated
Comment thread ledger/eval/prefetcher/prefetcher.go Outdated
Co-authored-by: cce <51567+cce@users.noreply.github.com>
@jannotti jannotti dismissed stale reviews from gmalouf and algorandskiy via 03c4b24 March 9, 2026 19:11
Comment thread util/pagedqueue.go Outdated
Comment thread ledger/eval/prefetcher/prefetcher_alignment_test.go Outdated
Comment thread ledger/eval/prefetcher/prefetcher_test.go
jannotti and others added 5 commits March 9, 2026 15:13
Comment thread util/pagedqueue.go
@jannotti jannotti merged commit 5621ecc into algorand:master Mar 10, 2026
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants