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

Fix accounts index generation at startup when we don't use disk index #4018

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

HaoranYi
Copy link

@HaoranYi HaoranYi commented Dec 9, 2024

Problem

During account's index generation at startup, one of the important steps is to find duplicated pubkeys and send them to clean.

However, the code path that finds duplicates at index generation, when disk index is disabled, is incorrect. And we are are not finding all the duplicates. This makes clean unable to clean old storages, and results in continue growing of account maps.

Note this only affects when the validator running with disk index disabled.

Summary of Changes

Fix finding duplicated (pubkey, slots) at start up when we disable disk index.

Fixes #

@HaoranYi HaoranYi marked this pull request as draft December 9, 2024 16:17
@HaoranYi HaoranYi force-pushed the fix_index_gen_no_disk branch from 067ce54 to 0a57a47 Compare December 10, 2024 18:58
@HaoranYi HaoranYi changed the title fix index gen no disk Fix accounts index generation at startup when we don't use disk index Dec 10, 2024
@HaoranYi
Copy link
Author

Graph of account's map before the fix.

image

@HaoranYi
Copy link
Author

Graph of account's map after the fix.
image

@HaoranYi HaoranYi marked this pull request as ready for review December 10, 2024 19:18
@brooksprumo
Copy link

Can you set the ACCOUNTS_INDEX_CONFIG_FOR_TESTING.index_limit_mb = IndexLimitMb::InMemOnly, and run the solana_runtime and solana_accounts_db tests?

@HaoranYi
Copy link
Author

Can you set the ACCOUNTS_INDEX_CONFIG_FOR_TESTING.index_limit_mb = IndexLimitMb::InMemOnly, and run the solana_runtime and solana_accounts_db tests?

Both tests passed.

test result: ok. 538 passed; 0 failed; 4 ignored; 0 measured; 0 filtered out; finished in 116.30s

     Running tests/accounts.rs (/home/sol/src/agave/target/debug/deps/accounts-06e1f00a7377d075)

running 2 tests
test test_shrink_and_clean ... ok
test test_bad_bank_hash ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 24.62s

     Running tests/stake.rs (/home/sol/src/agave/target/debug/deps/stake-c3f800f796ce426c)

running 4 tests
test test_stake_create_and_split_single_signature ... ok
test test_stake_create_and_split_to_existing_system_account ... ok
test test_create_stake_account_from_seed ... ok
test test_stake_account_lifetime ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.92s

   Doc-tests solana_runtime

running 1 test
test runtime/src/bank/builtins/core_bpf_migration/mod.rs - bank::builtins::core_bpf_migration::Bank::upgrade_core_bpf_program (line 287) ... ignored

test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s
sol@haoran-dev-ny:~/src/agave/accounts-db$ tail -n 20 accounts_db_test.log
test accounts_index::tests::test_new_entry_and_update_code_paths ... ok
test accounts_db::tests::test_shrink_ancient_overflow_with_min_size ... ok
test shared_buffer_reader::tests::test_shared_buffer_sweep ... ok
test ancient_append_vecs::tests::test_write_ancient_accounts ... ok
test ancient_append_vecs::tests::test_clear_should_shrink_after_cutoff_simple ... ok
test ancient_append_vecs::tests::test_calc_accounts_to_combine_many_refs ... ok
test ancient_append_vecs::tests::test_calc_accounts_to_combine_simple ... ok
test accounts_db::tests::test_shrink_collect_simple ... ok
test storable_accounts::tests::test_storable_accounts_by_slot ... ok
test accounts_db::scan_account_storage::tests::test_accountsdb_scan_snapshot_stores_binning::append_vec ... ok
test accounts_db::scan_account_storage::tests::test_accountsdb_scan_snapshot_stores_binning::hot_storage ... ok

test result: ok. 599 passed; 0 failed; 2 ignored; 0 measured; 0 filtered out; finished in 31.72s

Copy link

@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.

One real question, one double check, and some nits

accounts-db/src/accounts_db.rs Show resolved Hide resolved
accounts-db/src/accounts_index/in_mem_accounts_index.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_index/in_mem_accounts_index.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_index.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_index.rs Outdated Show resolved Hide resolved
accounts-db/src/accounts_index/in_mem_accounts_index.rs Outdated Show resolved Hide resolved
@HaoranYi HaoranYi requested a review from brooksprumo December 11, 2024 15:39
@brooksprumo brooksprumo self-requested a review December 11, 2024 18:29
@brooksprumo brooksprumo self-requested a review December 11, 2024 20:44
@HaoranYi HaoranYi force-pushed the fix_index_gen_no_disk branch 2 times, most recently from 8ca8733 to 819f026 Compare December 12, 2024 15:53
@HaoranYi
Copy link
Author

Rebase to master to pickup #4069

brooksprumo
brooksprumo previously approved these changes Dec 12, 2024
Copy link

@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.

:shipit:

Thanks for fixing this!

@jeffwashington
Copy link

is this change necessary since this just got merged?
#4044

@jeffwashington
Copy link

is this change necessary since this just got merged? #4044

it seems like we could simplify both disk and in-mem index startup code if we just simply identify the pubkeys that are dups. We no longer have to identify them by slot, I don't think.

@HaoranYi
Copy link
Author

HaoranYi commented Dec 12, 2024

is this change necessary since this just got merged? #4044

it seems like we could simplify both disk and in-mem index startup code if we just simply identify the pubkeys that are dups. We no longer have to identify them by slot, I don't think.

We still need to find all duplicated (key, slot) correctly. Duplicates are used for other things than clean too. Account data length and lattice hash both depends on finding the correct set of duplicated (key, slot) at startup.

@HaoranYi
Copy link
Author

HaoranYi commented Dec 12, 2024

With #4044 backported, we probably don't need to backport this one.

Account data len may be wrong for no-disk. But that's just used in a metrics. So should be fine to let it be wrong.

But we still need this in master for lattic hash in master.

// this for slot_list.len() == 1. For slot_list.len() > 1, the
// items, previously inserted into the slot_list, have already
// been added. We don't need to add them again.
if slot_list.len() == 1 {

Choose a reason for hiding this comment

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

there is a race here. 2 competing insert threads here could both find slot_list.len() = 1. Then, they serilialize access with the write lock on lock_and_update_slot_list so that one makes len 2, the next 3. I don't think this is bad in this case, but it is a race condition. lock_and_update_slot_list returns slot list len after insertion using write lock. We could set other_slot to None if lock_and_update_slot_list returns != 2, which means someone else won the race.

Copy link
Author

Choose a reason for hiding this comment

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

yeah. fixed in ef3e873.

@HaoranYi
Copy link
Author

HaoranYi commented Dec 12, 2024

it seems like we could simplify both disk and in-mem index startup code if we just simply identify the pubkeys that are dups. We no longer have to identify them by slot, I don't think.

We still need to populate (pubkey, slot) at startup.

This is because at startup, we use uncleaned_pubkeys to drive clean. And uncleaned_pubkeys require slot.

uncleaned_pubkeys: DashMap<Slot, Vec<Pubkey>>,

And the (pubkey, slot) is used here.

self.uncleaned_pubkeys.entry(slot).or_default().push(key);

Yes, with #4044 landed. We can

  1. get rid of uncleaned_root from clean.
  2. don't populate uncleaned_roots at startup.

But these works are out of scope of this PR.

I have two other follow up PRs for them #4095 and #4092.

@HaoranYi HaoranYi marked this pull request as draft December 12, 2024 22:00
@HaoranYi HaoranYi force-pushed the fix_index_gen_no_disk branch from ef3e873 to 482486f Compare December 13, 2024 00:01
@HaoranYi HaoranYi marked this pull request as ready for review December 13, 2024 00:50
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