From 3928259bb5b45d6fb201b0b8a0859c9aa29f2f90 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 11 May 2023 17:36:29 +0200 Subject: [PATCH] bench: add restore session benchmark Signed-off-by: Benjamin Bouvier --- Cargo.lock | 2 + benchmarks/Cargo.toml | 8 +- benchmarks/benches/store_bench.rs | 124 ++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 benchmarks/benches/store_bench.rs diff --git a/Cargo.lock b/Cargo.lock index bfd602696..8931283df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -537,6 +537,8 @@ name = "benchmarks" version = "1.0.0" dependencies = [ "criterion", + "matrix-sdk", + "matrix-sdk-base", "matrix-sdk-crypto", "matrix-sdk-sled", "matrix-sdk-sqlite", diff --git a/benchmarks/Cargo.toml b/benchmarks/Cargo.toml index fe065d358..a39272db6 100644 --- a/benchmarks/Cargo.toml +++ b/benchmarks/Cargo.toml @@ -9,10 +9,12 @@ publish = false [dependencies] criterion = { version = "0.4.0", features = ["async", "async_tokio", "html_reports"] } +matrix-sdk-base = { path = "../crates/matrix-sdk-base" } matrix-sdk-crypto = { path = "../crates/matrix-sdk-crypto", version = "0.6.0"} matrix-sdk-sqlite = { path = "../crates/matrix-sdk-sqlite", version = "0.1.0", default-features = false, features = ["crypto-store"] } -matrix-sdk-sled = { path = "../crates/matrix-sdk-sled", version = "0.2.0", default-features = false, features = ["crypto-store"] } +matrix-sdk-sled = { path = "../crates/matrix-sdk-sled", version = "0.2.0", features = ["crypto-store"] } matrix-sdk-test = { path = "../testing/matrix-sdk-test", version = "0.6.0"} +matrix-sdk = { path = "../crates/matrix-sdk" } ruma = { workspace = true } serde_json = { workspace = true } tempfile = "3.3.0" @@ -24,3 +26,7 @@ pprof = { version = "0.11.0", features = ["flamegraph", "criterion"] } [[bench]] name = "crypto_bench" harness = false + +[[bench]] +name = "store_bench" +harness = false diff --git a/benchmarks/benches/store_bench.rs b/benchmarks/benches/store_bench.rs new file mode 100644 index 000000000..203c8c423 --- /dev/null +++ b/benchmarks/benches/store_bench.rs @@ -0,0 +1,124 @@ +use criterion::*; +use matrix_sdk::{config::StoreConfig, Client, RoomInfo, RoomState, Session, StateChanges}; +use matrix_sdk_base::{store::MemoryStore, StateStore as _}; +use matrix_sdk_sled::SledStateStore; +use matrix_sdk_sqlite::SqliteStateStore; +use ruma::{device_id, user_id, RoomId}; +use tokio::runtime::Builder; + +fn criterion() -> Criterion { + #[cfg(target_os = "linux")] + let criterion = Criterion::default().with_profiler(pprof::criterion::PProfProfiler::new( + 100, + pprof::criterion::Output::Flamegraph(None), + )); + + #[cfg(not(target_os = "linux"))] + let criterion = Criterion::default(); + + criterion +} + +/// Number of joined rooms in the benchmark. +const NUM_JOINED_ROOMS: usize = 10000; + +/// Number of stripped rooms in the benchmark. +const NUM_STRIPPED_JOINED_ROOMS: usize = 10000; + +pub fn restore_session(c: &mut Criterion) { + let runtime = Builder::new_multi_thread().build().expect("Can't create runtime"); + + // Create a fake list of changes, and a session to recover from. + let mut changes = StateChanges::default(); + + for i in 0..NUM_JOINED_ROOMS { + let room_id = RoomId::parse(format!("!room{i}:example.com")).unwrap().to_owned(); + changes.add_room(RoomInfo::new(&room_id, RoomState::Joined)); + } + + for i in 0..NUM_STRIPPED_JOINED_ROOMS { + let room_id = RoomId::parse(format!("!strippedroom{i}:example.com")).unwrap().to_owned(); + changes.add_stripped_room(RoomInfo::new(&room_id, RoomState::Joined)); + } + + let session = Session { + access_token: "OHEY".to_owned(), + refresh_token: None, + user_id: user_id!("@somebody:example.com").to_owned(), + device_id: device_id!("DEVICE_ID").to_owned(), + }; + + // Start the benchmark. + + let mut group = c.benchmark_group("Client reload"); + group.throughput(Throughput::Elements(100)); + + const NAME: &str = "restore a session"; + + // Memory + let mem_store = MemoryStore::new(); + runtime.block_on(mem_store.save_changes(&changes)).expect("initial filling of mem failed"); + + group.bench_with_input(BenchmarkId::new("memory store", NAME), &mem_store, |b, store| { + b.to_async(&runtime).iter(|| async { + let client = Client::builder() + .homeserver_url("https://matrix.example.com") + .store_config(StoreConfig::new().state_store(store.clone())) + .build() + .await + .expect("Can't build client"); + client.restore_session(session.clone()).await.expect("couldn't restore session"); + }) + }); + + // Sled + let sled_path = tempfile::tempdir().unwrap().path().to_path_buf(); + let sled_store = + SledStateStore::builder().path(sled_path).build().expect("Can't create sled store"); + runtime.block_on(sled_store.save_changes(&changes)).expect("initial filling of sled failed"); + + group.bench_with_input(BenchmarkId::new("sled store", NAME), &sled_store, |b, store| { + b.to_async(&runtime).iter(|| async { + let client = Client::builder() + .homeserver_url("https://matrix.example.com") + .store_config(StoreConfig::new().state_store(store.clone())) + .build() + .await + .expect("Can't build client"); + client.restore_session(session.clone()).await.expect("couldn't restore session"); + }) + }); + + // Sqlite + let sqlite_dir = tempfile::tempdir().unwrap(); + let sqlite_store = runtime.block_on(SqliteStateStore::open(sqlite_dir.path(), None)).unwrap(); + runtime + .block_on(sqlite_store.save_changes(&changes)) + .expect("initial filling of sqlite failed"); + + group.bench_with_input(BenchmarkId::new("sqlite store", NAME), &sqlite_store, |b, store| { + b.to_async(&runtime).iter(|| async { + let client = Client::builder() + .homeserver_url("https://matrix.example.com") + .store_config(StoreConfig::new().state_store(store.clone())) + .build() + .await + .expect("Can't build client"); + client.restore_session(session.clone()).await.expect("couldn't restore session"); + }) + }); + + { + let _guard = runtime.enter(); + drop(sqlite_store); + } + + group.finish() +} + +criterion_group! { + name = benches; + config = criterion(); + targets = restore_session +} +criterion_main!(benches);