2020-09-17 07:05:16 -07:00
|
|
|
#![feature(test)]
|
|
|
|
|
|
|
|
extern crate test;
|
|
|
|
|
2021-05-26 08:15:46 -07:00
|
|
|
use {
|
|
|
|
rand::{thread_rng, Rng},
|
|
|
|
solana_gossip::{
|
2021-10-26 06:02:30 -07:00
|
|
|
crds::{Crds, GossipRoute, VersionedCrdsValue},
|
2021-05-26 08:15:46 -07:00
|
|
|
crds_shards::CrdsShards,
|
|
|
|
crds_value::CrdsValue,
|
|
|
|
},
|
|
|
|
solana_sdk::timing::timestamp,
|
|
|
|
std::iter::repeat_with,
|
|
|
|
test::Bencher,
|
removes delayed crds inserts when upserting gossip table (#16806)
It is crucial that VersionedCrdsValue::insert_timestamp does not go
backward in time:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L67-L79
Otherwise methods such as get_votes and get_epoch_slots_since will
break, which will break their downstream flow, including vote-listener
and optimistic confirmation:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1197-L1215
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1274-L1298
For that, Crds::new_versioned is intended to be called "atomically" with
Crds::insert_verioned (as the comment already says so):
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L126-L129
However, currently this is violated in the code. For example,
filter_pull_responses creates VersionedCrdsValues (with the current
timestamp), then acquires an exclusive lock on gossip, then
process_pull_responses writes those values to the crds table:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L2375-L2392
Depending on the workload and lock contention, the insert_timestamps may
well be in the past when these values finally are inserted into gossip.
To avoid such scenarios, this commit:
* removes Crds::new_versioned and Crd::insert_versioned.
* makes VersionedCrdsValue constructor private, only invoked in
Crds::insert, so that insert_timestamp is populated right before
insert.
This will improve insert_timestamp monotonicity as long as Crds::insert
is not called with a stalled timestamp. Following commits may further
improve this by calling timestamp() inside Crds::insert, and/or
switching to std::time::Instant which guarantees monotonicity.
2021-04-28 04:56:13 -07:00
|
|
|
};
|
2020-09-17 07:05:16 -07:00
|
|
|
|
|
|
|
const CRDS_SHARDS_BITS: u32 = 8;
|
|
|
|
|
removes delayed crds inserts when upserting gossip table (#16806)
It is crucial that VersionedCrdsValue::insert_timestamp does not go
backward in time:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L67-L79
Otherwise methods such as get_votes and get_epoch_slots_since will
break, which will break their downstream flow, including vote-listener
and optimistic confirmation:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1197-L1215
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1274-L1298
For that, Crds::new_versioned is intended to be called "atomically" with
Crds::insert_verioned (as the comment already says so):
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L126-L129
However, currently this is violated in the code. For example,
filter_pull_responses creates VersionedCrdsValues (with the current
timestamp), then acquires an exclusive lock on gossip, then
process_pull_responses writes those values to the crds table:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L2375-L2392
Depending on the workload and lock contention, the insert_timestamps may
well be in the past when these values finally are inserted into gossip.
To avoid such scenarios, this commit:
* removes Crds::new_versioned and Crd::insert_versioned.
* makes VersionedCrdsValue constructor private, only invoked in
Crds::insert, so that insert_timestamp is populated right before
insert.
This will improve insert_timestamp monotonicity as long as Crds::insert
is not called with a stalled timestamp. Following commits may further
improve this by calling timestamp() inside Crds::insert, and/or
switching to std::time::Instant which guarantees monotonicity.
2021-04-28 04:56:13 -07:00
|
|
|
fn new_test_crds_value<R: Rng>(rng: &mut R) -> VersionedCrdsValue {
|
|
|
|
let value = CrdsValue::new_rand(rng, None);
|
|
|
|
let label = value.label();
|
|
|
|
let mut crds = Crds::default();
|
2021-10-26 06:02:30 -07:00
|
|
|
crds.insert(value, timestamp(), GossipRoute::LocalMessage)
|
|
|
|
.unwrap();
|
2021-07-21 05:16:26 -07:00
|
|
|
crds.get::<&VersionedCrdsValue>(&label).cloned().unwrap()
|
2020-09-17 07:05:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_crds_shards_find(bencher: &mut Bencher, num_values: usize, mask_bits: u32) {
|
removes delayed crds inserts when upserting gossip table (#16806)
It is crucial that VersionedCrdsValue::insert_timestamp does not go
backward in time:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L67-L79
Otherwise methods such as get_votes and get_epoch_slots_since will
break, which will break their downstream flow, including vote-listener
and optimistic confirmation:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1197-L1215
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L1274-L1298
For that, Crds::new_versioned is intended to be called "atomically" with
Crds::insert_verioned (as the comment already says so):
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/crds.rs#L126-L129
However, currently this is violated in the code. For example,
filter_pull_responses creates VersionedCrdsValues (with the current
timestamp), then acquires an exclusive lock on gossip, then
process_pull_responses writes those values to the crds table:
https://github.com/solana-labs/solana/blob/ec37a843a/core/src/cluster_info.rs#L2375-L2392
Depending on the workload and lock contention, the insert_timestamps may
well be in the past when these values finally are inserted into gossip.
To avoid such scenarios, this commit:
* removes Crds::new_versioned and Crd::insert_versioned.
* makes VersionedCrdsValue constructor private, only invoked in
Crds::insert, so that insert_timestamp is populated right before
insert.
This will improve insert_timestamp monotonicity as long as Crds::insert
is not called with a stalled timestamp. Following commits may further
improve this by calling timestamp() inside Crds::insert, and/or
switching to std::time::Instant which guarantees monotonicity.
2021-04-28 04:56:13 -07:00
|
|
|
let mut rng = thread_rng();
|
|
|
|
let values: Vec<_> = repeat_with(|| new_test_crds_value(&mut rng))
|
2020-09-17 07:05:16 -07:00
|
|
|
.take(num_values)
|
|
|
|
.collect();
|
|
|
|
let mut shards = CrdsShards::new(CRDS_SHARDS_BITS);
|
|
|
|
for (index, value) in values.iter().enumerate() {
|
|
|
|
assert!(shards.insert(index, value));
|
|
|
|
}
|
|
|
|
bencher.iter(|| {
|
|
|
|
let mask = rng.gen();
|
|
|
|
let _hits = shards.find(mask, mask_bits).count();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_0(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_1(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_3(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_5(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 5);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_7(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 7);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_8(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn bench_crds_shards_find_9(bencher: &mut Bencher) {
|
|
|
|
bench_crds_shards_find(bencher, 100_000, 9);
|
|
|
|
}
|