diff --git a/Cargo.lock b/Cargo.lock index f69f3c2..3f07080 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloca" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4" +dependencies = [ + "cc", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -41,6 +50,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anstream" version = "0.6.21" @@ -540,6 +555,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.2.49" @@ -595,6 +616,33 @@ dependencies = [ "phf", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "4.5.53" @@ -718,6 +766,61 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "criterion" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf" +dependencies = [ + "alloca", + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "page_size", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4" +dependencies = [ + "cast", + "itertools 0.13.0", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -733,6 +836,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -1382,6 +1491,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1833,6 +1953,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -2134,6 +2263,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "openidconnect" version = "4.0.1" @@ -2328,6 +2463,16 @@ dependencies = [ "sha2", ] +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "parking" version = "2.2.1" @@ -2539,6 +2684,34 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "polling" version = "3.11.0" @@ -2778,6 +2951,26 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -3345,6 +3538,7 @@ version = "0.11.4" dependencies = [ "async-trait", "chrono", + "criterion", "derive_more", "password-auth", "password-hash", @@ -4137,6 +4331,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.10.0" @@ -4831,6 +5035,22 @@ dependencies = [ "wasite", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -4840,6 +5060,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.62.2" diff --git a/Cargo.toml b/Cargo.toml index 44a5d84..c7ff681 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,6 @@ opentelemetry = [ "dep:tracing-opentelemetry", ] - [profile.dev] debug = 0 @@ -149,6 +148,7 @@ openssl = { version = "0.10", features = ["vendored"] } async-std = { version = "1.13", features = ["attributes"] } similar-asserts = "1.7" insta = { version = "1.44", features = ["filters"] } +criterion = { version = "0.8", features = ["async_tokio"] } [dev-dependencies] rstest.workspace = true diff --git a/crates/store_sqlite/Cargo.toml b/crates/store_sqlite/Cargo.toml index 4011d25..47f7625 100644 --- a/crates/store_sqlite/Cargo.toml +++ b/crates/store_sqlite/Cargo.toml @@ -11,8 +11,13 @@ publish = false [features] test = ["dep:rstest"] +[[bench]] +name = "insert_calendar_object" +harness = false + [dev-dependencies] rstest.workspace = true +criterion.workspace = true [dependencies] tokio.workspace = true diff --git a/crates/store_sqlite/benches/ical_event.ics b/crates/store_sqlite/benches/ical_event.ics new file mode 100644 index 0000000..b5d4660 --- /dev/null +++ b/crates/store_sqlite/benches/ical_event.ics @@ -0,0 +1,47 @@ +BEGIN:VCALENDAR +CALSCALE:GREGORIAN +PRODID:-//Ximian//NONSGML Evolution Calendar//EN +VERSION:2.0 + +BEGIN:VTIMEZONE +TZID:Europe/Berlin +X-LIC-LOCATION:Europe/Berlin +BEGIN:DAYLIGHT +TZNAME:CEST +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +DTSTART:19810329T020000 +RRULE:FREQ=YEARLY;UNTIL=20370329T010000Z;BYDAY=-1SU;BYMONTH=3 +END:DAYLIGHT +BEGIN:STANDARD +TZNAME:CET +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +DTSTART:19961027T030000 +RRULE:FREQ=YEARLY;UNTIL=20361026T010000Z;BYDAY=-1SU;BYMONTH=10 +END:STANDARD +END:VTIMEZONE + + +BEGIN:VEVENT +UID:fa915b604e6e3f36772501ff869439e6a3c5cf67 +DTSTAMP:20250726T112617Z +DTSTART;VALUE=DATE:20250806 +DTEND;VALUE=DATE:20250807 +SEQUENCE:2 +SUMMARY:all day event +TRANSP:OPAQUE +CLASS:PUBLIC +CREATED:20250726T144426Z +LAST-MODIFIED:20250726T144426Z +BEGIN:VALARM +TRIGGER:-PT30M +REPEAT:2 +DURATION:PT15M +ACTION:DISPLAY +DESCRIPTION:Breakfast meeting with executive\n +team at 8:30 AM EST. +END:VALARM +END:VEVENT + +END:VCALENDAR diff --git a/crates/store_sqlite/benches/insert_calendar_object.rs b/crates/store_sqlite/benches/insert_calendar_object.rs new file mode 100644 index 0000000..1926075 --- /dev/null +++ b/crates/store_sqlite/benches/insert_calendar_object.rs @@ -0,0 +1,70 @@ +use criterion::{Criterion, criterion_group, criterion_main}; +use rustical_ical::{CalendarObject, CalendarObjectType}; +use rustical_store::{Calendar, CalendarMetadata, CalendarStore}; +use rustical_store_sqlite::tests::get_test_calendar_store; + +fn benchmark(c: &mut Criterion) { + let runtime = tokio::runtime::Runtime::new().unwrap(); + let cal_store = runtime.block_on(async { + let cal_store = get_test_calendar_store().await; + + cal_store + .insert_calendar(Calendar { + meta: CalendarMetadata { + displayname: Some("Yeet".to_owned()), + order: 0, + description: None, + color: None, + }, + principal: "user".to_owned(), + id: "okwow".to_owned(), + timezone_id: None, + deleted_at: None, + synctoken: 0, + subscription_url: None, + push_topic: "asd".to_owned(), + components: vec![ + CalendarObjectType::Event, + CalendarObjectType::Todo, + CalendarObjectType::Journal, + ], + }) + .await + .unwrap(); + cal_store + }); + + let object = CalendarObject::from_ics(include_str!("ical_event.ics").to_owned(), None).unwrap(); + + let batch_size = 1000; + let objects: Vec<_> = std::iter::repeat_n(object.clone(), batch_size).collect(); + + c.bench_function("put_batch", |b| { + b.to_async(&runtime).iter(async || { + // yeet + cal_store + .put_objects("user".to_owned(), "okwow".to_owned(), objects.clone(), true) + .await + .unwrap(); + }); + }); + + c.bench_function("put_single", |b| { + b.to_async(&runtime).iter(async || { + // yeet + for _ in 0..1000 { + cal_store + .put_object("user".to_owned(), "okwow".to_owned(), object.clone(), true) + .await + .unwrap(); + } + }); + }); + + runtime + .block_on(cal_store.delete_calendar("user", "okwow", false)) + .unwrap(); +} + +criterion_group!(benches, benchmark); +criterion_main!(benches);