Skip to content

ledger: Don't keep repeated slots in the leader schedule#9126

Merged
vadorovsky merged 1 commit intoanza-xyz:masterfrom
vadorovsky:leader-schedule-do-not-repeat
Mar 25, 2026
Merged

ledger: Don't keep repeated slots in the leader schedule#9126
vadorovsky merged 1 commit intoanza-xyz:masterfrom
vadorovsky:leader-schedule-do-not-repeat

Conversation

@vadorovsky
Copy link
Copy Markdown
Member

Problem

Leader schedule structs keep a vector with public keys that reflect the leadership of them for each slot. However, leaders always repeat for N slots (currently 4). That results in having a vector with each element being subsequently repeated for N times.

Summary of Changes

Reduce the size of vectors 4 times by storing only non-repeating leaders, then utilizing flattened std::iter::repeat and floor division to present the correct information to the callers of the LeaderSchedule trait.

@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch from a5744e9 to 28b9f63 Compare November 18, 2025 14:11
@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch from 28b9f63 to ab32710 Compare January 12, 2026 16:44
@mergify
Copy link
Copy Markdown

mergify Bot commented Jan 12, 2026

If this PR represents a change to the public RPC API:

  1. Make sure it includes a complementary update to rpc-client/ (example)
  2. Open a follow-up PR to update the JavaScript client @solana/kit (example)

Thank you for keeping the RPC clients in sync with the server API @vadorovsky.

@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch 4 times, most recently from 00e2390 to 9e01c16 Compare January 15, 2026 11:30
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 99.54545% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 83.3%. Comparing base (e304ac0) to head (f8a6480).
⚠️ Report is 23 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff            @@
##           master    #9126    +/-   ##
========================================
  Coverage    83.3%    83.3%            
========================================
  Files         845      845            
  Lines      319896   320030   +134     
========================================
+ Hits       266511   266641   +130     
- Misses      53385    53389     +4     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

vadorovsky added a commit to vadorovsky/agave that referenced this pull request Jan 15, 2026
Tests were constructing schedules with `repeat > 1` but feeding arrays
whose length wasn’t a multiple of `repeat`, so some leaders never
repeated the expected number of times. That inconsistency also blocks
follow-up work on optimizing the schedule calculation (see
anza-xyz#9126).

Add a debug assert that the schedule length is divisible by `repeat`,
and fix the tests to generate properly aligned schedules.

Change `TEST_SLOTS_PER_EPOCH` in rpc from 129 (an incorrect, unaligned
value) to 256, which stays above the delinquent-slot threshold while
keeping the tests fast.
vadorovsky added a commit to vadorovsky/agave that referenced this pull request Jan 15, 2026
Tests were constructing schedules with `repeat > 1` but feeding arrays
whose length wasn’t a multiple of `repeat`, so some leaders never
repeated the expected number of times. That inconsistency also blocks
follow-up work on optimizing the schedule calculation (see
anza-xyz#9126).

Add a debug assert that the schedule length is divisible by `repeat`,
and fix the tests to generate properly aligned schedules.

Change `TEST_SLOTS_PER_EPOCH` in rpc from 129 (an incorrect, unaligned
value) to 256, which stays above the delinquent-slot threshold while
keeping the tests fast.

Ref: anza-xyz#8280
vadorovsky added a commit to vadorovsky/agave that referenced this pull request Jan 15, 2026
Tests were constructing schedules with `repeat > 1` but feeding arrays
whose length wasn’t a multiple of `repeat`, so some leaders never
repeated the expected number of times. That inconsistency also blocks
follow-up work on optimizing the schedule calculation (see
anza-xyz#9126).

Add a debug assert that the schedule length is divisible by `repeat`,
and fix the tests to generate properly aligned schedules.

Change `TEST_SLOTS_PER_EPOCH` in rpc from 129 (an incorrect, unaligned
value) to 256, which stays above the delinquent-slot threshold while
keeping the tests fast.

Ref: anza-xyz#8280
github-merge-queue Bot pushed a commit that referenced this pull request Jan 16, 2026
Tests were constructing schedules with `repeat > 1` but feeding arrays
whose length wasn’t a multiple of `repeat`, so some leaders never
repeated the expected number of times. That inconsistency also blocks
follow-up work on optimizing the schedule calculation (see
#9126).

Add a debug assert that the schedule length is divisible by `repeat`,
and fix the tests to generate properly aligned schedules.

Change `TEST_SLOTS_PER_EPOCH` in rpc from 129 (an incorrect, unaligned
value) to 256, which stays above the delinquent-slot threshold while
keeping the tests fast.

Ref: #8280
@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch from 9e01c16 to d46fd8a Compare January 16, 2026 16:28
@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch 4 times, most recently from 7e1401f to 3d68019 Compare February 9, 2026 13:02
@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch 5 times, most recently from 75bec31 to 8475e2d Compare March 6, 2026 09:52
@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch 2 times, most recently from 4e76a2d to b1d981a Compare March 16, 2026 20:26
@vadorovsky vadorovsky marked this pull request as ready for review March 16, 2026 22:48
@vadorovsky
Copy link
Copy Markdown
Member Author

I will try to slowlana this tomorrow with some epoch boundary ledger, but it should become more visible when applied together with #8451

Copy link
Copy Markdown

@brooksprumo brooksprumo left a comment

Choose a reason for hiding this comment

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

I still need to go through get_leader_upcoming_slots(). Here's some quick comments though.

Comment thread leader-schedule/src/vote_keyed.rs Outdated
Comment thread leader-schedule/src/lib.rs Outdated
Comment thread leader-schedule/src/vote_keyed.rs Outdated
Comment on lines +90 to +92
// Find out how many slots from the starting chunk we still have to
// yield.
let offset_in_chunk = offset_in_epoch % repeat;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think there is an issue here if the offset_chunk is not in index.

If not found, then the offset in the chunk should be 0. But if offset_in_epoch is in the middle of a leader span (not the first slot of four, for example), then offset_in_chunk will be non-zero, skipping those initial slots of the next leader span.

So if .binary_search() returns Err, offset_in_chunk should be set to 0. Probably can match on the result to handle this?

Here's a test to put in test_get_leader_upcoming_slots_with_repeat():

        assert!(
            leader_schedule
                .get_leader_upcoming_slots(&leader_a.id, 5)
                .take(10)
                .eq([8, 9, 10, 11, 12, 13, 14, 15, 20, 21])
        );

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch! Fixed and added more tests.

@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch 2 times, most recently from 80c3058 to 9873863 Compare March 23, 2026 21:37
@vadorovsky vadorovsky requested a review from brooksprumo March 24, 2026 08:44
Comment thread leader-schedule/src/vote_keyed.rs
Comment thread leader-schedule/src/vote_keyed.rs
Comment thread leader-schedule/src/vote_keyed.rs
Comment thread leader-schedule/src/vote_keyed.rs Outdated
@vadorovsky vadorovsky requested a review from brooksprumo March 24, 2026 13:22
Copy link
Copy Markdown

@brooksprumo brooksprumo left a comment

Choose a reason for hiding this comment

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

lgtm

Leader schedule structs keep a vector with public keys that reflect
the leadership of them for each slot. However, leaders always repeat
for N slots (currently 4). That results in having a vector with each
element being subsequently repeated for N times.

Reduce the size of vectors 4 times by storing only non-repeating
leaders, then utilizing flattened `std::iter::repeat` and floor division
to present the correct information to the callers of the
`LeaderSchedule` trait.
@vadorovsky vadorovsky force-pushed the leader-schedule-do-not-repeat branch from 1972a00 to f8a6480 Compare March 24, 2026 15:19
@vadorovsky
Copy link
Copy Markdown
Member Author

I will try to slowlana this tomorrow with some epoch boundary ledger, but it should become more visible when applied together with #8451

There is no visible difference in profiles and the benchmark shows <1ms difference.

bench_epoch_turnover/1000_votes_1000000_stakes
                        time:   [170.86 ms 171.48 ms 171.86 ms]
bench_epoch_turnover/1000_votes_1000000_stakes
                        time:   [170.38 ms 171.17 ms 171.76 ms]
                        change: [−0.4884% −0.1299% +0.2657%] (p = 0.52 > 0.05)
                        No change in performance detected.

The main win from this PR is that we will be able to use SmallVec for leader slots, and therefore leaders with small enough amount of slots won't keep their slots in heap - I'm going to cook as the next change. It's also a prerequisite for #8451.

@vadorovsky vadorovsky added this pull request to the merge queue Mar 25, 2026
Merged via the queue into anza-xyz:master with commit 411fac8 Mar 25, 2026
51 checks passed
@vadorovsky vadorovsky deleted the leader-schedule-do-not-repeat branch March 25, 2026 06:27
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.

3 participants