-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Use a lock instead of atomics for snapshot Progress #11197
Conversation
Logs, docs and todos
…napshot`returns Rename `take_at` to `request_snapshot_at` Cleanup
Fix tests
Cut down on the logging noise
* master: Pause pruning while snapshotting (#11178) Type annotation for next_key() matching of json filter options (#11192) Crypto primitives removed from ethkey (#11174) Made ecrecover implementation trait public (#11188) Remove unused macro_use. (#11191) [dependencies]: jsonrpc `14.0.1` (#11183) [receipt]: add `sender` & `receiver` to `RichReceipts` (#11179) [dependencies] bump rand 0.7 (#11022) [ethcore/builtin]: do not panic in blake2pricer on short input (#11180) TxPermissions ver 3: gas price & data (#11170) [ethash] chainspec validate `ecip1017EraRounds` non-zero (#11123) util Host: fix a double Read Lock bug in fn Host::session_readable() (#11175) ethcore client: fix a double Read Lock bug in fn Client::logs() (#11172) Aura: Report malice on sibling blocks from the same validator (#11160)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While switching to locks makes the code more readable, there are things to be aware of, like it could introduce unpredictable latencies in a hot path e.g. here and makes it harder to reason about deadlocks (e.g. double lock on read()
from the same thread). But it seems to be fine in this case.
Co-Authored-By: Andronik Ordian <write@reusable.software>
Interesting you think that (I don't, tbh), @ngotchac had a similar comment. Not that it matters much ofc. I definitely agree that locks are much harder to reason about. |
@@ -44,89 +43,68 @@ pub enum Snapshotting { | |||
#[derive(Debug)] | |||
pub struct Progress { | |||
/// Number of accounts processed so far | |||
accounts: AtomicUsize, | |||
accounts: u64, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I like u64
instead usize
here
parity/snapshot_cmd.rs
Outdated
let cur_size = progress.bytes(); | ||
if cur_size != last_size { | ||
last_size = cur_size; | ||
let bytes = ::informant::format_bytes(cur_size as usize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will truncate u64
when usize::max_value() < u64::max_value()
, I don't know if it is an issue or if we just should change informant::format_bytes
to take an u64
instead usize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usize
s here come from the io methods deeper down the stack that actually write bytes; they all return usize
for the nr of bytes written. I wanted to be consistent and went with u64
but we can go the other way too if preferred. I don't have a strong opinion tbh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I don't have strong opinions of this but I think truncation casting
deserves a comment because it is not clear to me at least whether it is intended or bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went the other way in ee4a0a9 ad changed format_bytes()
to take a u64
instead.
last_size = cur_size; | ||
let bytes = ::informant::format_bytes(cur_size as usize); | ||
info!("Snapshot: {} accounts (state), {} blocks, {} bytes", p.accounts(), p.blocks(), bytes); | ||
loop { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how much slower this loop would execute w.r.t. reading a RwLock
instead of AtomicUsize
in each iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully using a RwLock
is faster, but I agree, a benchmark providing a hard number would be a good thing. The reason it's (hopefully) faster is there were several atomics getting written to with SeqCst
ordering in several places, so having a single lock is hopefully faster.
Cleanup
* master: (21 commits) ropsten #6631425 foundation #8798209 (#11201) Update list of bootnodes for xDai chain (#11236) ethcore/res: add mordor testnet configuration (#11200) [chain specs]: activate `Istanbul` on mainnet (#11228) [builtin]: support `multiple prices and activations` in chain spec (#11039) Insert explicit warning into the panic hook (#11225) Snapshot restoration overhaul (#11219) Fix docker centos build (#11226) retry on gitlab system failures (#11222) Update bootnodes. (#11203) Use provided usd-per-eth value if an endpoint is specified (#11209) Use a lock instead of atomics for snapshot Progress (#11197) [informant]: `MillisecondDuration` -> `as_millis()` (#11211) Step duration map configuration parameter ported from the POA Network fork (#10902) Upgrade jsonrpc to latest (#11206) [export hardcoded sync]: use debug for `H256` (#11204) Pause pruning while snapshotting (#11178) Type annotation for next_key() matching of json filter options (#11192) Crypto primitives removed from ethkey (#11174) Made ecrecover implementation trait public (#11188) ...
After #11178
snapshot::Progress
is a bit crowded. This PR sticks the whole struct inside aRwLock
.Not very interesting code here, but this change could use an extra eye or two to ensure I got the lock scope right.