Skip to content

Commit

Permalink
Benchmark for large futures (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
slawlor authored Feb 19, 2024
1 parent 7fa9823 commit 6fcdd60
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
5 changes: 5 additions & 0 deletions ractor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,8 @@ tracing-test = "0.2"
name = "actor"
harness = false
required-features = []

[[bench]]
name = "async_traits"
harness = false
required-features = []
132 changes: 132 additions & 0 deletions ractor/benches/async_traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright (c) Sean Lawlor
//
// This source code is licensed under both the MIT license found in the
// LICENSE-MIT file in the root directory of this source tree.

//! Benchmarks for specifically keeping large data on the stack. If the future
//! doesn't get boxed, this measures the relative performance impact
//!
//! Comparison of
//! `cargo bench --bench async_traits -p ractor --no-default-features -F tokio_runtime`
//! against
//! `cargo bench --bench async_traits -p ractor --no-default-features -F tokio_runtime,async-trait`
#[macro_use]
extern crate criterion;

use criterion::{BatchSize, Criterion};
#[cfg(feature = "cluster")]
use ractor::Message;
use ractor::{Actor, ActorProcessingErr, ActorRef};

#[allow(clippy::async_yields_async)]
fn big_stack_futures(c: &mut Criterion) {
const NUM_MSGS: usize = 50;
const NUM_BYTES: usize = 50_000;

struct LargeFutureActor {
num_msgs: usize,
}

struct LargeFutureActorState {
cmsg: usize,
data: [u64; NUM_BYTES],
}

struct LargeFutureActorMessage;
#[cfg(feature = "cluster")]
impl Message for LargeFutureActorMessage {}

#[cfg_attr(feature = "async-trait", ractor::async_trait)]
impl Actor for LargeFutureActor {
type Msg = LargeFutureActorMessage;

type State = LargeFutureActorState;

type Arguments = ();

async fn pre_start(
&self,
myself: ActorRef<Self::Msg>,
_: (),
) -> Result<Self::State, ActorProcessingErr> {
let _ = myself.cast(LargeFutureActorMessage);
Ok(LargeFutureActorState {
cmsg: 0usize,
data: [0; NUM_BYTES],
})
}

async fn handle(
&self,
myself: ActorRef<Self::Msg>,
_message: Self::Msg,
state: &mut Self::State,
) -> Result<(), ActorProcessingErr> {
state.cmsg += 1;
state.data[state.cmsg] = state.cmsg as u64;
if state.cmsg >= self.num_msgs {
myself.stop(None);
} else {
let _ = myself.cast(LargeFutureActorMessage);
}
Ok(())
}
}

let id =
format!("Waiting on {NUM_MSGS} messages with large data in the Future to be processed");
#[cfg(not(feature = "async-std"))]
let runtime = tokio::runtime::Builder::new_multi_thread().build().unwrap();
#[cfg(feature = "async-std")]
let _ = async_std::task::block_on(async {});
c.bench_function(&id, move |b| {
b.iter_batched(
|| {
#[cfg(not(feature = "async-std"))]
{
runtime.block_on(async move {
let (_, handle) =
Actor::spawn(None, LargeFutureActor { num_msgs: NUM_MSGS }, ())
.await
.expect("Failed to create test actor");
handle
})
}
#[cfg(feature = "async-std")]
{
async_std::task::block_on(async move {
let (_, handle) =
Actor::spawn(None, LargeFutureActor { num_msgs: NUM_MSGS }, ())
.await
.expect("Failed to create test actor");
handle
})
}
},
|handle| {
#[cfg(not(feature = "async-std"))]
{
runtime.block_on(async move {
let _ = handle.await;
})
}
#[cfg(feature = "async-std")]
{
async_std::task::block_on(async move {
let _ = handle.await;
})
}
},
BatchSize::PerIteration,
);
});
}

criterion_group! {
name=async_traits;
config = Criterion::default()
.sample_size(100);
targets=big_stack_futures
}
criterion_main!(async_traits);

0 comments on commit 6fcdd60

Please sign in to comment.