feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
//! Scaling benchmarks for the swactor runtime.
|
|
|
|
|
//!
|
|
|
|
|
//! These benchmarks measure how performance scales with:
|
|
|
|
|
//! - Number of actors
|
|
|
|
|
//! - Number of worker threads
|
|
|
|
|
//! - Message payload size
|
|
|
|
|
|
|
|
|
|
use crate::harness::{black_box, Bench, BenchSuite};
|
|
|
|
|
use std::thread;
|
|
|
|
|
use swactor::{
|
|
|
|
|
actor::ActorInterface,
|
2026-02-06 07:06:37 +00:00
|
|
|
runtime::{Ctx, Runtime, RuntimeConfig},
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Test Actors
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
/// A counter actor that just increments on each message
|
|
|
|
|
struct CounterActor {
|
|
|
|
|
count: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CounterActor {
|
|
|
|
|
fn new() -> Self {
|
|
|
|
|
Self { count: 0 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
struct Increment;
|
|
|
|
|
|
|
|
|
|
impl ActorInterface for CounterActor {
|
|
|
|
|
type Incoming = Increment;
|
|
|
|
|
type Response = ();
|
|
|
|
|
|
2026-02-05 15:54:03 +00:00
|
|
|
fn handle(&mut self, _ctx: &Ctx, _msg: Increment) {
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
self.count += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct SharedCounter {
|
|
|
|
|
count: std::sync::Arc<std::sync::atomic::AtomicUsize>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ActorInterface for SharedCounter {
|
|
|
|
|
type Incoming = Increment;
|
|
|
|
|
type Response = ();
|
|
|
|
|
|
2026-02-05 15:54:03 +00:00
|
|
|
fn handle(&mut self, _ctx: &Ctx, _msg: Increment) {
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
self.count
|
|
|
|
|
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// An actor that handles variable-sized payloads
|
|
|
|
|
struct PayloadActor {
|
|
|
|
|
bytes_received: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PayloadActor {
|
|
|
|
|
fn new() -> Self {
|
|
|
|
|
Self { bytes_received: 0 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
struct Payload(Vec<u8>);
|
|
|
|
|
|
|
|
|
|
impl ActorInterface for PayloadActor {
|
|
|
|
|
type Incoming = Payload;
|
|
|
|
|
type Response = ();
|
|
|
|
|
|
2026-02-05 15:54:03 +00:00
|
|
|
fn handle(&mut self, _ctx: &Ctx, msg: Payload) {
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
self.bytes_received += msg.0.len();
|
|
|
|
|
black_box(&msg.0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Benchmarks
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
/// Benchmark: How throughput scales with actor count
|
|
|
|
|
pub fn bench_actor_count_scaling(suite: &mut BenchSuite) {
|
2026-02-06 06:48:51 +00:00
|
|
|
for (actor_count, messages_per_actor, warmup_n, iters_n) in [
|
|
|
|
|
(10u64, 200u64, 5usize, 50usize),
|
|
|
|
|
(100, 200, 5, 30),
|
|
|
|
|
(500, 200, 5, 15),
|
|
|
|
|
(1000, 200, 5, 12),
|
|
|
|
|
] {
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
let name = format!("scaling_{}_actors", actor_count);
|
|
|
|
|
let total_messages = actor_count * messages_per_actor;
|
|
|
|
|
|
|
|
|
|
let result = Bench::new(&name)
|
2026-02-06 06:48:51 +00:00
|
|
|
.warmup(warmup_n)
|
|
|
|
|
.iters(iters_n)
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
.elements(total_messages)
|
|
|
|
|
.run_with_setup(
|
|
|
|
|
|| {
|
|
|
|
|
let config = RuntimeConfig {
|
|
|
|
|
max_actors: (actor_count as usize) + 100,
|
2026-02-05 15:54:03 +00:00
|
|
|
actor_max_messages: (total_messages as usize) * 3,
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
num_threads: 1,
|
2026-02-06 06:48:51 +00:00
|
|
|
..Default::default()
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
};
|
|
|
|
|
let runtime = Runtime::new(config);
|
|
|
|
|
|
|
|
|
|
// Spawn actors
|
|
|
|
|
let mut actors = Vec::with_capacity(actor_count as usize);
|
|
|
|
|
for _ in 0..actor_count {
|
|
|
|
|
let addr = runtime.spawn(CounterActor::new()).unwrap();
|
|
|
|
|
actors.push(addr);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-05 15:54:03 +00:00
|
|
|
// Process spawns
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
for _ in 0..(actor_count * 2) {
|
|
|
|
|
runtime.tick();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(runtime, actors, messages_per_actor)
|
|
|
|
|
},
|
|
|
|
|
|(runtime, actors, msgs_per)| {
|
|
|
|
|
// Distribute messages across all actors
|
|
|
|
|
for _ in 0..msgs_per {
|
|
|
|
|
for actor in &actors {
|
|
|
|
|
let _ = runtime.send_to::<Increment>(*actor, Increment);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process all
|
|
|
|
|
let total = actors.len() as u64 * msgs_per;
|
|
|
|
|
for _ in 0..(total * 3) {
|
|
|
|
|
runtime.tick();
|
|
|
|
|
}
|
|
|
|
|
black_box(());
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
suite.add(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Benchmark: How throughput scales with thread count (multithreaded runtime)
|
|
|
|
|
pub fn bench_thread_count_scaling(suite: &mut BenchSuite) {
|
|
|
|
|
let actor_count = 100u64;
|
|
|
|
|
let messages_per_actor = 500u64;
|
|
|
|
|
let total_messages = actor_count * messages_per_actor;
|
|
|
|
|
|
|
|
|
|
for thread_count in [2usize, 4, 8] {
|
|
|
|
|
let name = format!("scaling_{}_threads", thread_count);
|
|
|
|
|
|
|
|
|
|
let result = Bench::new(&name)
|
2026-02-06 06:48:51 +00:00
|
|
|
.warmup(5)
|
|
|
|
|
.iters(30)
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
.elements(total_messages)
|
|
|
|
|
.run_with_setup(
|
|
|
|
|
|| {
|
|
|
|
|
let counter = std::sync::Arc::new(std::sync::atomic::AtomicUsize::new(0));
|
|
|
|
|
let config = RuntimeConfig {
|
|
|
|
|
max_actors: (actor_count as usize) + 100,
|
2026-02-05 15:54:03 +00:00
|
|
|
actor_max_messages: (total_messages as usize) * 3,
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
num_threads: thread_count,
|
2026-02-06 06:48:51 +00:00
|
|
|
..Default::default()
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
};
|
|
|
|
|
let runtime = Runtime::new(config);
|
|
|
|
|
|
|
|
|
|
let mut actors = Vec::with_capacity(actor_count as usize);
|
|
|
|
|
for _ in 0..actor_count {
|
|
|
|
|
let addr = runtime
|
|
|
|
|
.spawn(SharedCounter {
|
|
|
|
|
count: counter.clone(),
|
|
|
|
|
})
|
|
|
|
|
.unwrap();
|
|
|
|
|
actors.push(addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let handle = runtime.run().unwrap();
|
|
|
|
|
|
|
|
|
|
for actor in &actors {
|
|
|
|
|
loop {
|
|
|
|
|
if handle
|
|
|
|
|
.runtime
|
|
|
|
|
.send_to::<Increment>(*actor, Increment)
|
|
|
|
|
.is_ok()
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
thread::yield_now();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while counter.load(std::sync::atomic::Ordering::Relaxed) < actors.len() {
|
|
|
|
|
thread::yield_now();
|
|
|
|
|
}
|
|
|
|
|
counter.store(0, std::sync::atomic::Ordering::Relaxed);
|
|
|
|
|
|
|
|
|
|
(handle, actors, counter)
|
|
|
|
|
},
|
|
|
|
|
|(handle, actors, counter)| {
|
|
|
|
|
for _ in 0..messages_per_actor {
|
|
|
|
|
for actor in &actors {
|
|
|
|
|
let _ = handle.runtime.send_to::<Increment>(*actor, Increment);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while counter.load(std::sync::atomic::Ordering::Relaxed)
|
|
|
|
|
< total_messages as usize
|
|
|
|
|
{
|
|
|
|
|
thread::yield_now();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle.shutdown();
|
|
|
|
|
handle.join();
|
|
|
|
|
black_box(());
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
suite.add(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Benchmark: How throughput scales with message payload size
|
|
|
|
|
pub fn bench_payload_size_scaling(suite: &mut BenchSuite) {
|
2026-02-06 06:48:51 +00:00
|
|
|
let message_count = 3_000u64;
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
|
|
|
|
|
for payload_size in [64usize, 1024, 16384, 65536] {
|
|
|
|
|
let name = format!("payload_{}B", payload_size);
|
|
|
|
|
let payload = vec![0u8; payload_size];
|
|
|
|
|
|
|
|
|
|
let result = Bench::new(&name)
|
2026-02-06 06:48:51 +00:00
|
|
|
.warmup(5)
|
|
|
|
|
.iters(40)
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
.elements(message_count)
|
|
|
|
|
.run_with_setup(
|
|
|
|
|
|| {
|
|
|
|
|
let config = RuntimeConfig {
|
|
|
|
|
max_actors: 10,
|
|
|
|
|
actor_max_messages: (message_count as usize) * 2,
|
|
|
|
|
num_threads: 1,
|
2026-02-06 06:48:51 +00:00
|
|
|
..Default::default()
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
};
|
|
|
|
|
let runtime = Runtime::new(config);
|
|
|
|
|
let sink = runtime.spawn(PayloadActor::new()).unwrap();
|
|
|
|
|
|
2026-02-05 15:54:03 +00:00
|
|
|
// Process spawn
|
feat: Stress tests, benchmarking, and non-failing queues and inboxes #3
Adds some basic benchmarking, stress tests. They still need to be properly examined to ensure they are testing the correct properties, but fit for "good enough". Implements the HybridChannel type, which features a channel buffer that can withstand overflows. It does so by providing a dequeue behind a mutex. Without overflow, will push messages into the lock free ArrayQueue implemented by crossbeam_queue; when that buffer fills, will use the locking portion provided by the Mutex<VecDequeue>.
In the future we can even further optimize this, perhaps with some linked list implementations of lock-free channels, but, like the benchmarks, this fits the "good enough" bar for now.
2026-01-26 07:14:00 +00:00
|
|
|
for _ in 0..10 {
|
|
|
|
|
runtime.tick();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(runtime, sink, payload.clone())
|
|
|
|
|
},
|
|
|
|
|
|(runtime, sink, payload)| {
|
|
|
|
|
for _ in 0..message_count {
|
|
|
|
|
let _ = runtime.send_to::<Payload>(sink, Payload(payload.clone()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _ in 0..(message_count * 3) {
|
|
|
|
|
runtime.tick();
|
|
|
|
|
}
|
|
|
|
|
black_box(());
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
suite.add(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Run all scaling benchmarks
|
|
|
|
|
pub fn run_all() -> BenchSuite {
|
|
|
|
|
let mut suite = BenchSuite::new("Scaling Benchmarks");
|
|
|
|
|
|
|
|
|
|
println!("\nRunning actor count scaling benchmarks...");
|
|
|
|
|
bench_actor_count_scaling(&mut suite);
|
|
|
|
|
|
|
|
|
|
println!("Running thread count scaling benchmarks...");
|
|
|
|
|
bench_thread_count_scaling(&mut suite);
|
|
|
|
|
|
|
|
|
|
println!("Running payload size scaling benchmarks...");
|
|
|
|
|
bench_payload_size_scaling(&mut suite);
|
|
|
|
|
|
|
|
|
|
suite
|
|
|
|
|
}
|