Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Uses SeqLock for CachedAccountInner::hash #33696

Merged

Conversation

brooksprumo
Copy link
Contributor

@brooksprumo brooksprumo commented Oct 13, 2023

Problem

The CachedAccountInner::hash field is protected with an RwLock to ensure the cached account hash is read/written safely. Since Hash is Copy, we can use a lighter-weight synchronization mechanism that is faster than RwLock.

Summary of Changes

Use SeqLock instead of RwLock for CachedAccountInner::hash.

A sequence lock read needs just two atomic loads, and a write locks a mutex plus does two atomic stores. Readers will retry if there is a write in between their two loads. Since we always need a hash value (i.e. non-reference), we're not wasting any time copying bytes around either.

Performance Comparisons

Here's some results micro-benchmarking[1] results from my macbook. This compares SeqLock with RwLock from std and parking_lot.

[1]: Here's the code for the benchmark: https://github.com/brooksprumo/seqlock/blob/master/benches/bench_seqlock.rs

First is when there are only readers:
only readers

And here's about 50/50 readers and writers:
readers and writers

I know micro-benchmarks are not really indicative of true speedups, but hopefully this shows that SeqLock is orders of magnitude faster than std's RwLock. Any reduction in lock contention will likely have a positive result on the system as a whole.

@brooksprumo brooksprumo force-pushed the seqlock/cached-account-hash branch from 73427be to 18de3ac Compare October 18, 2023 03:49
@brooksprumo brooksprumo marked this pull request as ready for review October 18, 2023 04:19
@codecov
Copy link

codecov bot commented Oct 18, 2023

Codecov Report

Merging #33696 (18de3ac) into master (0b05e8d) will increase coverage by 0.0%.
Report is 2 commits behind head on master.
The diff coverage is 100.0%.

@@           Coverage Diff           @@
##           master   #33696   +/-   ##
=======================================
  Coverage    81.8%    81.8%           
=======================================
  Files         806      806           
  Lines      217894   217893    -1     
=======================================
+ Hits       178252   178262   +10     
+ Misses      39642    39631   -11     

@alessandrod
Copy link
Contributor

Great stuff, this seems like the ideal case for a seqlock: the hash is small so even in the write contended case readers will likely never spin more than once or twice. Death to syscalls!

@alessandrod
Copy link
Contributor

[1]: Here's the code for the benchmark: https://github.com/brooksprumo/seqlock/blob/master/benches/bench_seqlock.rs

Sorry I'm doing a lot of cargo build today so I have time to kill 😂 You could make the bench more realistic by holding [u8; 32] inside the locks, and making sure the rwlock benches copy the array too

@brooksprumo
Copy link
Contributor Author

You could make the bench more realistic by holding [u8; 32] inside the locks, and making sure the rwlock benches copy the array too

Yep! I thought about doing this, but initially wanted the seqlock repo to just benchmark the locking and not any effects from copying. I agree that using a [u8; 32] would better match our use case here though!

@brooksprumo
Copy link
Contributor Author

Sorry I'm doing a lot of cargo build today so I have time to kill 😂

Thank you for taking the time to look/review!

Copy link
Contributor

@HaoranYi HaoranYi left a comment

Choose a reason for hiding this comment

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

Nice. lgtm.

@brooksprumo
Copy link
Contributor Author

Now that solana-labs/solana-program-library#5597 has merged, SPL builds should be good too.

@brooksprumo brooksprumo merged commit e96678b into solana-labs:master Oct 18, 2023
@brooksprumo brooksprumo deleted the seqlock/cached-account-hash branch October 18, 2023 14:43
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants