diff --git a/Cargo.toml b/Cargo.toml index 39fa3f2..9515634 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ tracing = { version = "0.1", features = ["log"] } [dev-dependencies] assert_matches = "1.5" clap = { version = "4", features = ["derive"] } +criterion = { version = "0.5", features = ["async_tokio"] } maplit = "1" pretty_env_logger = "0.5" rustyline = "11" @@ -39,6 +40,7 @@ serde_json = "1" tokio = { version = "1", features = ["full"] } tracing-test = { version = "0.2", features = ["no-env-filter"] } tarantool-test-container = { path = "tarantool-test-container" } +rusty_tarantool = "*" [[example]] name = "cli_client" @@ -52,6 +54,14 @@ name = "transactions" [[example]] name = "call" +[[bench]] +name = "bench" +harness = false + +[[bench]] +name = "compare" +harness = false + [workspace] members = [ "tarantool-test-container", diff --git a/benches/bench.rs b/benches/bench.rs new file mode 100644 index 0000000..931b62a --- /dev/null +++ b/benches/bench.rs @@ -0,0 +1,67 @@ +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use futures::{future::try_join_all, TryFutureExt}; +use tarantool_rs::{Connection, ExecutorExt}; + +type TarantoolTestContainer = tarantool_test_container::TarantoolTestContainer< + tarantool_test_container::TarantoolDefaultArgs, +>; + +pub fn bench_tarantool_rs(c: &mut Criterion) { + let mut group = c.benchmark_group("tarantool_rs"); + + // Preparations + let tokio_rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .expect("Tokio multithread runtime built"); + let container = TarantoolTestContainer::default(); + let conn = tokio_rt + .block_on(async { + Connection::builder() + .build(format!("127.0.0.1:{}", container.connect_port())) + .await + }) + .expect("Connection created successfully"); + + // Bench logic + // NOTE: on my PC converting to join add slight overhead (1-2 microseconds for 1 future input) + // NOTE: on my PC 50 input load tarantool to 50% on single core + for parallel in [1, 2, 5, 10, 50].into_iter() { + group.bench_with_input(BenchmarkId::new("ping", parallel), ¶llel, |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| conn.ping(); + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }); + group.bench_with_input(BenchmarkId::new("call", parallel), ¶llel, |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| conn.call("gcinfo", ()); + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }); + group.bench_with_input( + BenchmarkId::new("eval, pass and decode echo response", parallel), + ¶llel, + |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| { + conn.eval("return ...", (1, "two", true)) + .and_then(|resp| async { + resp.decode_full::<(i64, String, bool)>() + .map_err(Into::into) + }) + }; + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }, + ); + } + + group.finish(); +} + +criterion_group!(benches, bench_tarantool_rs,); +criterion_main!(benches); diff --git a/benches/compare.rs b/benches/compare.rs new file mode 100644 index 0000000..167a99d --- /dev/null +++ b/benches/compare.rs @@ -0,0 +1,98 @@ +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use futures::{future::try_join_all, TryFutureExt}; +use tarantool_rs::{Connection, ExecutorExt}; + +type TarantoolTestContainer = tarantool_test_container::TarantoolTestContainer< + tarantool_test_container::TarantoolDefaultArgs, +>; + +pub fn compare_tarantool_rs_and_rusty_tarantool(c: &mut Criterion) { + let mut group = c.benchmark_group("compare_with_rusty_tarantool"); + + // Preparations + let tokio_rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .expect("Tokio multithread runtime built"); + let container = TarantoolTestContainer::default(); + let tt_addr = || format!("127.0.0.1:{}", container.connect_port()); + let conn = tokio_rt + .block_on(async { Connection::builder().build(tt_addr()).await }) + .expect("Connection created successfully"); + let conn_rusty = tokio_rt + .block_on(async { + let conn = + rusty_tarantool::tarantool::ClientConfig::new(tt_addr(), "guest", "").build(); + conn.ping().await?; + Result::<_, anyhow::Error>::Ok(conn) + }) + .expect("Connection (RustyTarantool) created successfully"); + + // Bench logic + // NOTE: on my PC converting to join add slight overhead (1-2 microseconds for 1 future input) + // NOTE: on my PC 50 input load tarantool to 50% on single core + for parallel in [1, 2, 5, 10, 50].into_iter() { + group.bench_with_input( + BenchmarkId::new("tarantool_rs ping", parallel), + ¶llel, + |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| conn.ping(); + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }, + ); + group.bench_with_input( + BenchmarkId::new("tarantool_rs eval", parallel), + ¶llel, + |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| { + conn.eval("return ...", (1, "two", true)) + .and_then(|resp| async { + resp.decode_full::<(i64, String, bool)>() + .map_err(Into::into) + }) + }; + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }, + ); + + group.bench_with_input( + BenchmarkId::new("RustyTarantool ping", parallel), + ¶llel, + |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| conn_rusty.ping(); + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }, + ); + group.bench_with_input( + BenchmarkId::new("RustyTarantool eval", parallel), + ¶llel, + |b, p| { + b.to_async(&tokio_rt).iter(|| async { + let make_fut = |_| { + conn_rusty + .eval("return ...", &(1, "two", true)) + .and_then(|resp| async { + resp.decode::<(i64, String, bool)>().map_err(Into::into) + }) + }; + let futures = try_join_all((0..*p).map(make_fut)); + futures.await.expect("Successful bench"); + }) + }, + ); + } + + group.finish(); +} + +criterion_group!(benches, compare_tarantool_rs_and_rusty_tarantool); +criterion_main!(benches);