Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clean scan optimization: scan disk index only for zero lamport #2879

Merged
merged 8 commits into from
Oct 3, 2024

Conversation

HaoranYi
Copy link

@HaoranYi HaoranYi commented Sep 9, 2024

Problem

Generally, we don't need to scan disk index for clean because disk index only contains single ref single entry account index, which is nearly always "alive" and shouldn't be cleaned, except for one special case - single ref zero accounts (single ref zero accounts need to be cleaned).

Currently, we scan disk index for every candidate, which can be optimized to only scan disk index for zeros.

Summary of Changes

optimize clean scan.

  1. add is_zero mark on cleaning info.
  2. only scan disk index for is_zero candidate.

Fixes #

@HaoranYi HaoranYi marked this pull request as draft September 9, 2024 19:39
@HaoranYi HaoranYi force-pushed the accounts-db/clean_scan_opt branch 3 times, most recently from 5f2c5ff to f557e79 Compare September 10, 2024 22:08
@HaoranYi HaoranYi force-pushed the accounts-db/clean_scan_opt branch from f557e79 to 5cda868 Compare September 24, 2024 20:41
@HaoranYi HaoranYi marked this pull request as ready for review September 24, 2024 21:01
@HaoranYi HaoranYi changed the title clean scan optimization clean scan optimization: scan disk index only for zeros Sep 25, 2024
accounts-db/src/accounts_db.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_db.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_db.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_db.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_db.rs Outdated Show resolved Hide resolved
.accounts
.scan_pubkeys(|pubkey| self.insert_pubkey(&candidates, *pubkey));

store.accounts.scan_index(|index| {

Choose a reason for hiding this comment

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

Ah, I missed this the first time. We're using scan_index() now, instead of scan_pubkeys(). I think this is fine. With AppendVecs this is basically no additional cost. With Tiered Storage, it shouldn't be much additional work to get the is-zero-lamports information (esp once tiered storage has the lamports optimizations).

Copy link
Author

Choose a reason for hiding this comment

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

yeah. we need to read the accounts meta. but it shouldn't be expensive.

accounts-db/src/append_vec.rs Outdated Show resolved Hide resolved
if candidate_info.might_contain_zero_lamport_entry {
ScanFilter::All
} else {
self.scan_filter_for_shrinking

Choose a reason for hiding this comment

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

Can you remind me where self.scan_filter_for_shrinking is set (and what the value is)?

Copy link
Author

@HaoranYi HaoranYi Sep 25, 2024

Choose a reason for hiding this comment

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

https://github.com/anza-xyz/agave/blob/master/validator/src/main.rs#L1274-L1285

It is set by the CLI.
default is "all", so no impact if not passed by CLI.

Maybe we should rename the CLI in a future PR, as it is not just for shrinking but also for cleaning.

Comment on lines +3200 to +3201
let is_zero_lamport = index.index_info.lamports == 0;
insert_candidate(pubkey, is_zero_lamport);

Choose a reason for hiding this comment

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

As we're scanning here, what happens in the case where this index_info is not zero lamport, but there is another index entry for this pubkey that is zero lamport? If we end up with setting might_contain_zero_lamport_entry to false, will that prevent the later scan from looking on disk and finding the other zero lamport entry?

Copy link
Author

@HaoranYi HaoranYi Sep 25, 2024

Choose a reason for hiding this comment

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

No. if it was true, then it will still be true, I think. We are oring is_zero_lamport.

            candidates_bin
                .entry(pubkey)
                .or_default()
                .might_contain_zero_lamport_entry |= is_zero_lamport;

Choose a reason for hiding this comment

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

Yes, I understand if a different entry for the same pubkey sets might_contain_zero_lamport_entry to true, then other falses will not reset the field to false.

My question is, when looking at the dirty stores, what if there's a pubkey A in dirty storage slot 100, with non-zero lamports. Also assume pubkey A is in non dirty storage slot 7 with zero lamports. It looks to me that we'd only look at storage 100 and not storage 7, so the clean candidate would say "nope, no zero lamport entries here" and then the scan filter would not look on disk for the other index entries.

I think after typing that out, I can see why it won't happen. If we have a dirty storage at slot 100, then the index entry for pubkey A must be in the in-memory index, as the slot-list will be 2 in this example. So only looking in-mem is safe, and we don't need to look on disk.

Does that sound right?

Copy link
Author

Choose a reason for hiding this comment

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

Ah. I see what you mean.
Yes, you are correct. If there are other instances of the account outside of the stores that we scan, then disk index is irrelevant because it will always be in memory.

@HaoranYi HaoranYi changed the title clean scan optimization: scan disk index only for zeros clean scan optimization: scan disk index only for zero lamport Sep 26, 2024
@jeffwashington
Copy link

i think this is correct. I need to look at this again monday. Do you have a machine monitoring this? Do we have a metric that shows us the difference in clean disk index loads?

@HaoranYi
Copy link
Author

Yes, it is running on dev12 (3gB7) since yesterday.
I am starting a base line master for comparison now. I will report the result soon.

@HaoranYi
Copy link
Author

HaoranYi commented Sep 28, 2024

image

clean scan time stats
red: master
blue: this PR.

It looks like blue is lower and better.

Note that from 8:00-11:00CST we don't have any metrics recorded because the certificate of solama metrics is expired.

@@ -3226,7 +3249,7 @@ impl AccountsDb {
let is_candidate_for_clean =
max_slot_inclusive >= *slot && latest_full_snapshot_slot >= *slot;
if is_candidate_for_clean {
self.insert_pubkey(&candidates, *pubkey);
insert_candidate(*pubkey, true);

Choose a reason for hiding this comment

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

why is this 'true'?

Choose a reason for hiding this comment

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

ah, because we are iterating zero_lamport_accounts_to_purge_after_full_snapshot

Copy link
Author

Choose a reason for hiding this comment

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

yes. exactly!

@jeffwashington
Copy link

@HaoranYi can you please show metric comparison for:
scan_missing on clean_accounts?
Should be close to 0 on normal machines and a lot higher on your machine.

@jeffwashington jeffwashington self-requested a review September 30, 2024 20:17
@HaoranYi
Copy link
Author

@HaoranYi can you please show metric comparison for: scan_missing on clean_accounts? Should be close to 0 on normal machines and a lot higher on your machine.

image

blue: this PR.
red: master

Yes, missing is much higher with this PR. But on normal machine, missing is small but not close to zero (between 5-6K per minute).

@HaoranYi
Copy link
Author

I think it is not zero because we are adding dead store back to "dirty stores"
at the end of cleaning-shrinking cycle.

dead_slots.insert(*slot);

And those dead storages are not dropped until next clean starts (This is
required and is correct). When next clean starts, all the keys in those dead
stores are populated as candidates, which could be missing from the index.
That's why "missing" is not zero.

@jeffwashington
Copy link

@HaoranYi can you please show metric comparison for: scan_missing on clean_accounts? Should be close to 0 on normal machines and a lot higher on your machine.

image

blue: this PR. red: master

Yes, missing is much higher with this PR. But on normal machine, missing is small but not close to zero (between 5-6K per minute).

ok, this graph shows the savings. This many disk lookups are avoided to get the same results.

Copy link

@jeffwashington jeffwashington left a comment

Choose a reason for hiding this comment

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

lgtm

if candidate_info.might_contain_zero_lamport_entry {
ScanFilter::All
} else {
self.scan_filter_for_shrinking
Copy link

@jeffwashington jeffwashington Sep 30, 2024

Choose a reason for hiding this comment

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

note that until we change the default of this cli arg, we'll have no impact on clean (or shrink) due to this filtering scan thing. default is ScanFilter::All

So, once this goes in, we need long term testing of setting scan filter to abnormal only.

@HaoranYi HaoranYi merged commit b23e636 into anza-xyz:master Oct 3, 2024
40 checks passed
@HaoranYi
Copy link
Author

HaoranYi commented Oct 3, 2024

This has been running fine on mainnet for a week. So merge it.

@HaoranYi HaoranYi deleted the accounts-db/clean_scan_opt branch October 3, 2024 14:08
ray-kast pushed a commit to abklabs/agave that referenced this pull request Nov 27, 2024
…xyz#2879)

* clean scan optimization

* fix rebase conflicts

* Update accounts-db/src/accounts_db.rs

Co-authored-by: Brooks <[email protected]>

* Update accounts-db/src/accounts_db.rs

Co-authored-by: Brooks <[email protected]>

* Update accounts-db/src/accounts_db.rs

Co-authored-by: Brooks <[email protected]>

* Update accounts-db/src/accounts_db.rs

Co-authored-by: Brooks <[email protected]>

* review update

* revert ZeroLamport trait for IndexInfoInner

---------

Co-authored-by: HaoranYi <[email protected]>
Co-authored-by: Brooks <[email protected]>
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