Skip to content

Commit

Permalink
test(consensus): modify the test cases in ingress payload serializati…
Browse files Browse the repository at this point in the history
…on/deserialization benchmarks (#3447)

Currently we only measure how much it takes to deserialize/serialize
ingress payloads with 2000/4000/6000/8000 messages each of size 1KB.
With the changes in this PR we will instead measure the following test
cases:
1. 1000 messages, 4KB each
2. 2000 messages, 4KB each
3. 1 message, 4MB
4. 1 message, 8MB

which resembles more closely the current limits on the ingress payload,
from both number of messages and message sizes extremes.

Also, in the deserialization benchmark we moved out the `clone()` as it
affects the measurements significantly.
  • Loading branch information
kpop-dfinity authored Jan 14, 2025
1 parent f72bd1c commit fe42b70
Showing 1 changed file with 35 additions and 23 deletions.
58 changes: 35 additions & 23 deletions rs/consensus/benches/validate_payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! in the past payloads, and the user signature is checked eventually, and
//! the message validates successfully
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
use dkg::DkgDataPayload;
use ic_artifact_pool::{consensus_pool::ConsensusPoolImpl, ingress_pool::IngressPoolImpl};
use ic_config::state_manager::Config as StateManagerConfig;
Expand Down Expand Up @@ -80,7 +80,7 @@ const PAST_PAYLOAD_HEIGHT: u64 = 4;
/// Ingress history size: 5 min worth of messages at 1000/sec = 300K.
const INGRESS_HISTORY_SIZE: usize = 300_000;

fn run_test<T>(_test_name: &str, test_fn: T)
fn run_test<T>(test_fn: T)
where
T: FnOnce(Time, &mut ConsensusPoolImpl, &dyn PayloadBuilder),
{
Expand Down Expand Up @@ -233,13 +233,18 @@ fn setup_ingress_state(now: Time, state_manager: &mut StateManagerImpl) {
/// Prepares the ingress payload which has 1K x specified number of
/// SignedIngress messages. The payload is filled with the specified 'seed'
/// bytes
fn prepare_ingress_payload(now: Time, message_count: usize, seed: u8) -> IngressPayload {
fn prepare_ingress_payload(
now: Time,
message_count: usize,
message_size: usize,
seed: u8,
) -> IngressPayload {
let mut ingress_msgs = Vec::new();
let expiry = std::time::Duration::from_secs(MAX_INGRESS_TTL.as_secs() - 1);
for i in 0..message_count {
let ingress = SignedIngressBuilder::new()
.method_name("provisional_create_canister_with_cycles")
.method_payload(vec![seed; INGRESS_MESSAGE_SIZE])
.method_payload(vec![seed; message_size])
.nonce(i as u64)
.expiry_time(now + expiry)
.canister_id(IC_00)
Expand Down Expand Up @@ -269,7 +274,7 @@ fn add_past_blocks(
for i in 1..=to_add {
let mut block = Block::from_parent(&parent);
block.rank = Rank(i);
let ingress = prepare_ingress_payload(now, message_count, i as u8);
let ingress = prepare_ingress_payload(now, message_count, INGRESS_MESSAGE_SIZE, i as u8);
block.payload = Payload::new(
ic_types::crypto::crypto_hash,
BlockPayload::Data(DataPayload {
Expand Down Expand Up @@ -336,15 +341,15 @@ fn validate_payload_benchmark(criterion: &mut Criterion) {

for message_count in (50..=850).step_by(50) {
run_test(
"validate_payload_benchmark",
|now: Time,
consensus_pool: &mut ConsensusPoolImpl,
payload_builder: &dyn PayloadBuilder| {
let tip = add_past_blocks(consensus_pool, now, message_count);
let pool_reader = PoolReader::new(consensus_pool);

let seed = CERTIFIED_HEIGHT + PAST_PAYLOAD_HEIGHT + 10;
let ingress = prepare_ingress_payload(now, message_count, seed as u8);
let ingress =
prepare_ingress_payload(now, message_count, INGRESS_MESSAGE_SIZE, seed as u8);
let payload = Payload::new(
ic_types::crypto::crypto_hash,
BlockPayload::Data(DataPayload {
Expand All @@ -359,8 +364,7 @@ fn validate_payload_benchmark(criterion: &mut Criterion) {
}),
);

let name = format!("validate_payload_{}", message_count);
group.bench_function(&name, |bench| {
group.bench_function(format!("validate_payload_{}", message_count), |bench| {
bench.iter(|| {
validate_payload(now, &payload, &pool_reader, &tip, payload_builder)
.expect("Invalid payload")
Expand All @@ -372,31 +376,39 @@ fn validate_payload_benchmark(criterion: &mut Criterion) {
}

fn serialization_benchmark(criterion: &mut Criterion) {
let mut group = criterion.benchmark_group("serialization");
group.sample_size(30);
let mut group = criterion.benchmark_group("ingress_payload_serialization_deserialization");
group.sample_size(50);
group.measurement_time(std::time::Duration::from_secs(10));

for message_count in (2000..=8000).step_by(2000) {
for (message_count, message_size_kb, tag) in [
(1_000, 4_000, "1000x4KB"),
(2_000, 4_000, "2000x4KB"),
(1, 4_000_000, "1x4MB"),
(1, 8_000_000, "1x8MB"),
] {
run_test(
"serialization_benchmark",
|now: Time, _: &mut ConsensusPoolImpl, _: &dyn PayloadBuilder| {
let seed = CERTIFIED_HEIGHT + PAST_PAYLOAD_HEIGHT + 10;
let ingress = prepare_ingress_payload(now, message_count, seed as u8);
let name = format!("serialization_{}_kb_payload", message_count);
group.bench_function(&name, |bench| {
let ingress =
prepare_ingress_payload(now, message_count, message_size_kb, seed as u8);

group.bench_function(format!("serialization_{tag}"), |bench| {
bench.iter(|| {
let proto: pb::IngressPayload = (&ingress).into();
black_box(proto);
})
});
let name = format!("deserialization_{}_kb_payload", message_count);
group.bench_function(&name, |bench| {

group.bench_function(format!("deserialization_{tag}"), |bench| {
let p: pb::IngressPayload = (&ingress).into();
bench.iter(|| {
let proto = p.clone();
let deser: IngressPayload = proto.try_into().unwrap();
black_box(deser);
})
bench.iter_batched(
|| p.clone(),
|proto| {
let deser: IngressPayload = proto.try_into().unwrap();
black_box(deser);
},
BatchSize::LargeInput,
)
});
},
)
Expand Down

0 comments on commit fe42b70

Please sign in to comment.