diff --git a/Cargo.lock b/Cargo.lock index d0d33d314..3e267d828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,6 +154,12 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + [[package]] name = "base64" version = "0.21.7" @@ -178,6 +184,17 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f" +[[package]] +name = "benches" +version = "0.0.0" +dependencies = [ + "criterion", + "nostr", + "nostr-database", + "nostr-sdk", + "tokio", +] + [[package]] name = "bindgen" version = "0.69.5" @@ -187,7 +204,7 @@ dependencies = [ "bitflags 2.11.0", "cexpr", "clang-sys", - "itertools", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -301,6 +318,12 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cbc" version = "0.1.2" @@ -365,6 +388,33 @@ dependencies = [ "zeroize", ] +[[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 = "cipher" version = "0.4.4" @@ -508,6 +558,58 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +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" @@ -523,6 +625,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-common" version = "0.1.7" @@ -1314,6 +1422,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 = "itoa" version = "1.0.18" @@ -1953,6 +2070,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "nwc" version = "0.44.0" @@ -2001,6 +2127,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 = "opaque-debug" version = "0.3.1" @@ -2309,6 +2441,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" @@ -2961,6 +3113,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.11.0" diff --git a/Cargo.toml b/Cargo.toml index 27dff007b..415e22c52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,39 +1,43 @@ [workspace] members = [ - "crates/*", + "crates/*", - # Nostr SDK - "sdk", + # Nostr SDK + "sdk", - # Nostr Database - "database/nostr-database", - "database/nostr-database-test-suite", - "database/nostr-lmdb", - "database/nostr-memory", - "database/nostr-ndb", - "database/nostr-sqlite", + # Nostr Database + "database/nostr-database", + "database/nostr-database-test-suite", + "database/nostr-lmdb", + "database/nostr-memory", + "database/nostr-ndb", + "database/nostr-sqlite", - # Gossip - "gossip/nostr-gossip", - "gossip/nostr-gossip-memory", - "gossip/nostr-gossip-sqlite", - "gossip/nostr-gossip-test-suite", + # Gossip + "gossip/nostr-gossip", + "gossip/nostr-gossip-memory", + "gossip/nostr-gossip-sqlite", + "gossip/nostr-gossip-test-suite", - # Remote File Storage implementations - "rfs/nostr-blossom", - "rfs/nostr-http-file-storage", + # Remote File Storage implementations + "rfs/nostr-blossom", + "rfs/nostr-http-file-storage", - # Signers - "signer/nostr-browser-signer", - "signer/nostr-browser-signer-proxy", - "signer/nostr-connect", + # Signers + "signer/nostr-browser-signer", + "signer/nostr-browser-signer-proxy", + "signer/nostr-connect", + "benches", ] default-members = ["crates/*"] resolver = "2" [workspace.package] edition = "2024" -authors = ["Yuki Kishimoto ", "Rust Nostr Developers"] +authors = [ + "Yuki Kishimoto ", + "Rust Nostr Developers", +] homepage = "https://github.com/rust-nostr/nostr" repository = "https://github.com/rust-nostr/nostr.git" license = "MIT" @@ -41,7 +45,7 @@ rust-version = "1.85.0" [workspace.dependencies] async-utility = "0.3" -async-wsocket = { git = "https://github.com/shadowylab/async-wsocket", rev = "0fed6c9c6aec7393ee0e9cf3933d76914ab427d3" } +async-wsocket = { git = "https://github.com/shadowylab/async-wsocket", rev = "0fed6c9c6aec7393ee0e9cf3933d76914ab427d3" } atomic-destructor = { version = "0.3", default-features = false } base64 = { version = "0.22", default-features = false } btreecap = "0.1" diff --git a/benches/Cargo.toml b/benches/Cargo.toml new file mode 100644 index 000000000..3d7d90b42 --- /dev/null +++ b/benches/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "benches" +version = "0.0.0" +edition.workspace = true +authors.workspace = true +license.workspace = true +publish = false +autobins = false + +[dependencies] +criterion = { version = "0.7", features = ["html_reports"] } +nostr = { workspace = true, features = ["std", "os-rng"] } +nostr-sdk.workspace = true +nostr-database = { workspace = true, features = ["flatbuf"] } +tokio.workspace = true + +[[bench]] +name = "bench_main" +path = "src/main.rs" +harness = false + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bench)'] } diff --git a/benches/src/database.rs b/benches/src/database.rs new file mode 100644 index 000000000..287f303dd --- /dev/null +++ b/benches/src/database.rs @@ -0,0 +1,48 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::Criterion; +use nostr::prelude::*; +use nostr_database::flatbuffers::FlatBufferDecodeBorrowed; +use nostr_database::{FlatBufferBuilder, FlatBufferEncode}; + +pub fn decode_flatbuf_event_borrow(c: &mut Criterion) { + let json = r#"{ + "content": "+", + "created_at": 1716508454, + "id": "3e9e9c2fbf263590860a9c60a7de6b0d166230a5a15aa8dcdb70f537cec9807a", + "kind": 7, + "pubkey": "3bbddb5c7233ad993b41cb639e63122120f391b8580a9b83aae33c648230e0a3", + "sig": "3f2ba6d713e4851500b81de2d2ef44b72f1eff061898bf8488e74f7e4ed141b0dadab4c3a9c6b237f3a6db83171bd41eafd7ab973f6fb067a4305e95abeadeee", + "tags": [ + [ + "e", + "e1e786c60ed884b6e784712aaf70e63b848b7403ef651b52b701d87739ea1808", + "", + "", + "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9" + ], + [ + "p", + "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9" + ] + ] + }"#; + let event = Event::from_json(json).unwrap(); + + let mut fbb = FlatBufferBuilder::new(); + let bytes = event.encode(&mut fbb); + + c.bench_function("decode_flatbuf_event_borrow", |bh| { + bh.iter(|| { + black_box(EventBorrow::decode(bytes)).unwrap(); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + decode_flatbuf_event_borrow(c); +} diff --git a/benches/src/event.rs b/benches/src/event.rs new file mode 100644 index 000000000..44d4cef9f --- /dev/null +++ b/benches/src/event.rs @@ -0,0 +1,85 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::Criterion; +use nostr::prelude::*; + +const ID: &str = "2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45"; + +fn deserialize_event(c: &mut Criterion) { + let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; + c.bench_function("deserialize_event", |bh| { + bh.iter(|| black_box(Event::from_json(json)).unwrap()) + }); +} + +fn serialize_event(c: &mut Criterion) { + let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; + let event = Event::from_json(json).unwrap(); + c.bench_function("serialize_event", |bh| { + bh.iter(|| black_box(event.as_json())) + }); +} + +fn event_check_pow(c: &mut Criterion) { + let json = r#"{"id":"000006d11924b38e55275637c6401965c54f9ae05ffed89bce0edc1720984656","pubkey":"385c3a6ec0b9d57a4330dbd6284989be5bd00e41c535f9ca39b6ae7c521b81cd","created_at":1759497131,"kind":1,"tags":[["nonce","1180727","20"]],"content":"This is a Nostr message with embedded proof-of-work","sig":"0b216dfa714db2f146f9fa7cf20954c3fd5a2dabf69cd30ab58cf142a7ebe0fd3f4bc8e9c261245dabc0be8f942ec15d3fe3ce4dcbe81df01ceb4ced91739f52"}"#; + let event = Event::from_json(json).unwrap(); + c.bench_function("event_check_pow", |bh| { + bh.iter(|| black_box(event.check_pow(16))) + }); +} + +fn verify_event_id(c: &mut Criterion) { + let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; + let event = Event::from_json(json).unwrap(); + c.bench_function("verify_event_id", |bh| { + bh.iter(|| black_box(event.verify_id())) + }); +} + +fn verify_event_sig(c: &mut Criterion) { + let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; + let event = Event::from_json(json).unwrap(); + c.bench_function("verify_event_sig", |bh| { + bh.iter(|| black_box(event.verify_signature())) + }); +} + +fn parse_event_id_from_hex(c: &mut Criterion) { + c.bench_function("parse_event_id_from_hex", |bh| { + bh.iter(|| black_box(EventId::from_hex(ID)).unwrap()) + }); +} + +fn parse_ephemeral_kind(c: &mut Criterion) { + c.bench_function("parse_ephemeral_kind", |bh| { + bh.iter(|| black_box(Kind::from(29_999))) + }); +} + +fn parse_kind(c: &mut Criterion) { + c.bench_function("parse_kind", |bh| bh.iter(|| black_box(Kind::from(0)))); +} + +fn builder_to_event(c: &mut Criterion) { + let keys = Keys::generate(); + c.bench_function("builder_to_event", |bh| { + bh.iter(|| black_box(EventBuilder::text_note("hello").sign_with_keys(&keys)).unwrap()) + }); +} + +pub fn benches(c: &mut Criterion) { + deserialize_event(c); + serialize_event(c); + event_check_pow(c); + verify_event_id(c); + verify_event_sig(c); + + parse_event_id_from_hex(c); + parse_ephemeral_kind(c); + parse_kind(c); + builder_to_event(c); +} diff --git a/benches/src/filter.rs b/benches/src/filter.rs new file mode 100644 index 000000000..7d5c90835 --- /dev/null +++ b/benches/src/filter.rs @@ -0,0 +1,49 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; +use std::str::FromStr; + +use criterion::Criterion; +use nostr::prelude::*; + +fn filter_match_event(c: &mut Criterion) { + // Event + let event = + Event::new( + EventId::from_hex("70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5") + .unwrap(), + PublicKey::from_hex("379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe") + .unwrap(), + Timestamp::from(1612809991), + Kind::TextNote, + [ + Tag::public_key(PublicKey::from_hex("b2d670de53b27691c0c3400225b65c35a26d06093bcc41f48ffc71e0907f9d4a").unwrap()), + Tag::public_key(PublicKey::from_hex("379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe").unwrap()), + Tag::event(EventId::from_hex("7469af3be8c8e06e1b50ef1caceba30392ddc0b6614507398b7d7daa4c218e96").unwrap()), + Tag::from_standardized(TagStandard::Kind { kind: Kind::TextNote, uppercase: false }), + ], + "#JoininBox is a minimalistic, security focused Linux environment for #JoinMarket with a terminal based graphical menu.\n\nnostr:npub14tq8m9ggnnn2muytj9tdg0q6f26ef3snpd7ukyhvrxgq33vpnghs8shy62 ๐Ÿ‘๐Ÿงก\n\nhttps://www.nobsbitcoin.com/joininbox-v0-8-0/", + Signature::from_str("273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502").unwrap(), + ); + + // Filter + let pk = + PublicKey::from_hex("b2d670de53b27691c0c3400225b65c35a26d06093bcc41f48ffc71e0907f9d4a") + .unwrap(); + let filter = Filter::new() + .pubkey(pk) + .search("linux") + .kind(Kind::TextNote); + + c.bench_function("filter_match_event", |bh| { + bh.iter(|| { + black_box(filter.match_event(&event, MatchEventOptions::new())); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + filter_match_event(c); +} diff --git a/benches/src/keys.rs b/benches/src/keys.rs new file mode 100644 index 000000000..c19806224 --- /dev/null +++ b/benches/src/keys.rs @@ -0,0 +1,80 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::Criterion; +use nostr::prelude::*; + +const NIP21_URI: &str = "nostr:npub14f8usejl26twx0dhuxjh9cas7keav9vr0v8nvtwtrjqx3vycc76qqh9nsy"; +const HEX: &str = "aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4"; +const BECH32: &str = "npub14f8usejl26twx0dhuxjh9cas7keav9vr0v8nvtwtrjqx3vycc76qqh9nsy"; + +fn parse_public_key_nip21_uri(c: &mut Criterion) { + c.bench_function("parse_public_key_nip21_uri", |bh| { + bh.iter(|| { + black_box(PublicKey::parse(NIP21_URI)).unwrap(); + }) + }); +} + +fn parse_public_key_hex(c: &mut Criterion) { + c.bench_function("parse_public_key_hex", |bh| { + bh.iter(|| { + black_box(PublicKey::parse(HEX)).unwrap(); + }) + }); +} + +fn parse_public_key_bech32(c: &mut Criterion) { + c.bench_function("parse_public_key_bech32", |bh| { + bh.iter(|| { + black_box(PublicKey::parse(BECH32)).unwrap(); + }) + }); +} + +fn public_key_from_bech32(c: &mut Criterion) { + c.bench_function("public_key_from_bech32", |bh| { + bh.iter(|| { + black_box(PublicKey::from_bech32(BECH32)).unwrap(); + }) + }); +} + +fn public_key_to_bech32(c: &mut Criterion) { + let public_key = PublicKey::from_hex(HEX).unwrap(); + c.bench_function("public_key_to_bech32", |bh| { + bh.iter(|| { + black_box(public_key.to_bech32()).unwrap(); + }) + }); +} + +fn public_key_from_hex(c: &mut Criterion) { + c.bench_function("public_key_from_hex", |bh| { + bh.iter(|| { + black_box(PublicKey::from_hex(HEX)).unwrap(); + }) + }); +} + +fn public_key_to_hex(c: &mut Criterion) { + let public_key = PublicKey::from_hex(HEX).unwrap(); + c.bench_function("public_key_to_hex", |bh| { + bh.iter(|| { + black_box(public_key.to_hex()); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + parse_public_key_nip21_uri(c); + parse_public_key_hex(c); + parse_public_key_bech32(c); + public_key_from_bech32(c); + public_key_to_bech32(c); + public_key_from_hex(c); + public_key_to_hex(c); +} diff --git a/benches/src/lib.rs b/benches/src/lib.rs new file mode 100644 index 000000000..6886a8546 --- /dev/null +++ b/benches/src/lib.rs @@ -0,0 +1,30 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +#![cfg(bench)] + +mod database; +mod event; +mod filter; +mod keys; +mod message; +mod nips; +mod parser; +mod relay; +mod tags; +mod types; + +criterion::criterion_group!( + benches, + nips::benches, + keys::benches, + tags::benches, + event::benches, + relay::benches, + types::benches, + filter::benches, + message::benches, + parser::benches, + database::benches, +); diff --git a/benches/src/main.rs b/benches/src/main.rs new file mode 100644 index 000000000..e0122b874 --- /dev/null +++ b/benches/src/main.rs @@ -0,0 +1,12 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +#[cfg(bench)] +criterion::criterion_main!(benches::benches); + +#[cfg(not(bench))] +fn main() { + println!("No benchmarks without cfg=bench"); + println!("Run with RUSTFLAGS='--cfg=bench -Awarnings'"); +} diff --git a/benches/src/message.rs b/benches/src/message.rs new file mode 100644 index 000000000..0a96f624b --- /dev/null +++ b/benches/src/message.rs @@ -0,0 +1,43 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::Criterion; +use nostr::prelude::*; + +fn parse_machine_readable_prefix(c: &mut Criterion) { + c.bench_function("parse_machine_readable_prefix", |bh| { + bh.iter(|| { + black_box(MachineReadablePrefix::parse( + "blocked: you are banned from posting here", + )) + .unwrap(); + }) + }); +} + +fn parse_ok_relay_message(c: &mut Criterion) { + let json: &str = r#"["OK", "70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5", true, "pow: difficulty 25>=24"]"#; + c.bench_function("parse_ok_relay_message", |bh| { + bh.iter(|| { + black_box(RelayMessage::from_json(&json)).unwrap(); + }) + }); +} + +fn parse_event_relay_message(c: &mut Criterion) { + let json: &str = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502"}]"#; + c.bench_function("parse_event_relay_message", |bh| { + bh.iter(|| { + black_box(RelayMessage::from_json(&json)).unwrap(); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + parse_machine_readable_prefix(c); + parse_ok_relay_message(c); + parse_event_relay_message(c); +} diff --git a/benches/src/nips.rs b/benches/src/nips.rs new file mode 100644 index 000000000..0c1fb65f7 --- /dev/null +++ b/benches/src/nips.rs @@ -0,0 +1,43 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; +use std::str::FromStr; + +use criterion::Criterion; +use nostr::prelude::*; + +fn parse_coordinate(c: &mut Criterion) { + let coordinate: &str = + "30023:aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4:ipsum"; + + c.bench_function("parse_coordinate", |bh| { + bh.iter(|| black_box(Coordinate::parse(coordinate)).unwrap()) + }); +} + +fn to_bech32_nevent(c: &mut Criterion) { + let event_id = + EventId::from_hex("d94a3f4dd87b9a3b0bed183b32e916fa29c8020107845d1752d72697fe5309a5") + .unwrap(); + let public_key = + PublicKey::from_str("32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245") + .unwrap(); + let relays = [ + RelayUrl::parse("wss://r.x.com").unwrap(), + RelayUrl::parse("wss://djbas.sadkb.com").unwrap(), + ]; + let nip19_event = Nip19Event::new(event_id).author(public_key).relays(relays); + + c.bench_function("to_bech32_nevent", |bh| { + bh.iter(|| { + black_box(nip19_event.to_bech32()).unwrap(); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + parse_coordinate(c); + to_bech32_nevent(c); +} diff --git a/benches/src/parser.rs b/benches/src/parser.rs new file mode 100644 index 000000000..8db42be84 --- /dev/null +++ b/benches/src/parser.rs @@ -0,0 +1,46 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::Criterion; +use nostr::prelude::*; + +const PARSER: NostrParser = NostrParser::new(); + +fn parse_text_with_nostr_uris(c: &mut Criterion) { + let text: &str = "I have never been very active in discussions but working on rust-nostr (at the time called nostr-rs-sdk) since September 2022 ๐Ÿฆ€ \n\nIf I remember correctly there were also nostr:nprofile1qqsqfyvdlsmvj0nakmxq6c8n0c2j9uwrddjd8a95ynzn9479jhlth3gpvemhxue69uhkv6tvw3jhytnwdaehgu3wwa5kuef0dec82c33w94xwcmdd3cxketedsux6ertwecrgues0pk8xdrew33h27pkd4unvvpkw3nkv7pe0p68gat58ycrw6ps0fenwdnvva48w0mzwfhkzerrv9ehg0t5wf6k2qgnwaehxw309ac82unsd3jhqct89ejhxtcpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhsh8njvk and nostr:nprofile1qqswuyd9ml6qcxd92h6pleptfrcqucvvjy39vg4wx7mv9wm8kakyujgpypmhxue69uhkx6r0wf6hxtndd94k2erfd3nk2u3wvdhk6w35xs6z7qgwwaehxw309ahx7uewd3hkctcpypmhxue69uhkummnw3ezuetfde6kuer6wasku7nfvuh8xurpvdjj7a0nq40"; + + c.bench_function("parse_text_with_nostr_uris", |bh| { + bh.iter(|| { + black_box(PARSER.parse(text).collect::>()); + }) + }); +} + +fn parse_text_with_urls(c: &mut Criterion) { + let text: &str = "I've uses both the book and rustlings: https://github.com/rust-lang/rustlings/\n\nThere is also the \"Rust by example\" book: https://doc.rust-lang.org/rust-by-example/\n\nWhile you read the book, try to make projects from scratch (not just simple ones). At the end, writing code is the best way to learn it."; + + c.bench_function("parse_text_with_urls", |bh| { + bh.iter(|| { + black_box(PARSER.parse(text).collect::>()); + }) + }); +} + +fn parse_text_with_hashtags(c: &mut Criterion) { + let text: &str = "Hey #rust-nostr fans, can you enlighten me please:\nWhen I am calculating my Web of Trust I do the following:\n0. Create client with outbox model enabled\n1. Get my follows, mutes, reports in one fetch call\n2. Get follows, mutes, reports of my follows in another fetch call, using an authors filter that has all follows in it\n3. Calculate scores with my weights locally\n\nQuestion:\nWhy did step 2. take hours to complete?\n\nIt seems like it's trying to connect to loads of relays.\nMy guess is either I am doing sth horribly wrong or there is no smart relay set calculation for filters in the pool.\n\nIn ndk this calculation takes under 10 seconds to complete, even without any caching. It will first look at the filters and calculate a relay set that has all authors in it then does the fetching.\n\n#asknostr #rust"; + + c.bench_function("parse_text_with_hashtags", |bh| { + bh.iter(|| { + black_box(PARSER.parse(text).collect::>()); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + parse_text_with_nostr_uris(c); + parse_text_with_urls(c); + parse_text_with_hashtags(c); +} diff --git a/benches/src/relay.rs b/benches/src/relay.rs new file mode 100644 index 000000000..d4cf47732 --- /dev/null +++ b/benches/src/relay.rs @@ -0,0 +1,45 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; +use std::sync::LazyLock; + +use criterion::Criterion; +use nostr_sdk::relay::inner::create_relay; +use tokio::runtime::Runtime; + +static RUNTIME: LazyLock = LazyLock::new(|| Runtime::new().unwrap()); + +fn handle_relay_msg_event(c: &mut Criterion) { + let relay = create_relay(); + + let msg = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502"}]"#; + + c.bench_function("handle_relay_msg_event", |bh| { + bh.iter(|| { + RUNTIME.block_on(async { + black_box(relay.handle_raw_relay_message(msg).await).unwrap(); + }); + }) + }); +} + +fn handle_relay_msg_invalid_event(c: &mut Criterion) { + let relay = create_relay(); + + let msg = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"fa163f5cfb75d77d9b6269011872ee22b34fb48d23251e9879bb1e4ccbdd8aaaf4b6dc5f5084a65ef42c52fbcde8f3178bac3ba207de827ec513a6aa39fa684c"}]"#; + + c.bench_function("handle_relay_msg_invalid_event", |bh| { + bh.iter(|| { + RUNTIME.block_on(async { + _ = black_box(relay.handle_raw_relay_message(msg).await); + }); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + handle_relay_msg_event(c); + handle_relay_msg_invalid_event(c); +} diff --git a/benches/src/tags.rs b/benches/src/tags.rs new file mode 100644 index 000000000..e294d9a19 --- /dev/null +++ b/benches/src/tags.rs @@ -0,0 +1,309 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::{BatchSize, Criterion}; +use nostr::prelude::*; + +fn generate_tags(n: usize) -> Tags { + let half = n / 2; + + let mut pubkeys = Vec::with_capacity(half); + + let mut tags = Vec::with_capacity(n); + + for _ in 0..half { + let keys = Keys::generate(); + + // Save pubkey + pubkeys.push(keys.public_key()); + + // Push simple p tag + tags.push(Tag::public_key(keys.public_key())); + } + + for pk in pubkeys.into_iter() { + // Push long p tag + let long_p_tag = Tag::from_standardized_without_cell(TagStandard::PublicKey { + public_key: pk, + relay_url: Some(RelayUrl::parse("wss://relay.damus.io").unwrap()), + uppercase: false, + alias: None, + }); + tags.push(long_p_tag) + } + + Tags::from_list(tags) +} + +fn generate_keys(c: &mut Criterion) { + c.bench_function("generate_keys", |bh| { + bh.iter(|| black_box(Keys::generate())) + }); +} + +fn tags_dedup_10_tags(c: &mut Criterion) { + let tags = generate_tags(10); + c.bench_function("tags_dedup_10_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags) + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_dedup_50_tags(c: &mut Criterion) { + let tags = generate_tags(50); + + c.bench_function("tags_dedup_50_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags); + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_dedup_100_tags(c: &mut Criterion) { + let tags = generate_tags(100); + + c.bench_function("tags_dedup_100_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags); + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_dedup_500_tags(c: &mut Criterion) { + let tags = generate_tags(500); + + c.bench_function("tags_dedup_500_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags); + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_dedup_1000_tags(c: &mut Criterion) { + let tags = generate_tags(1000); + + c.bench_function("tags_dedup_1000_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags); + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_dedup_2000_tags(c: &mut Criterion) { + let tags = generate_tags(2000); + + c.bench_function("tags_dedup_2000_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags); + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_dedup_4000_tags(c: &mut Criterion) { + let tags = generate_tags(4000); + + c.bench_function("tags_dedup_4000_tags", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.dedup(); + black_box(tags); + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_push(c: &mut Criterion) { + let tags = Tags::with_capacity(10); + + c.bench_function("tags_push", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.push(Tag::protected()); + black_box(tags) + }, + BatchSize::SmallInput, + ) + }); +} + +fn vec_tag_push(c: &mut Criterion) { + let tags = Vec::with_capacity(10); + + c.bench_function("vec_tag_push", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + tags.push(Tag::protected()); + black_box(tags) + }, + BatchSize::SmallInput, + ) + }); +} + +fn tags_pop(c: &mut Criterion) { + let tags = generate_tags(4000); + + c.bench_function("tags_pop", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + black_box(tags.pop()); + }, + BatchSize::SmallInput, + ) + }); +} + +fn vec_tag_pop(c: &mut Criterion) { + let tags = generate_tags(4000); + let tags = tags.to_vec(); + + c.bench_function("vec_tag_pop", |bh| { + bh.iter_batched( + || tags.clone(), + |mut tags| { + black_box(tags.pop()); + }, + BatchSize::SmallInput, + ) + }); +} + +fn get_tag_kind(c: &mut Criterion) { + let tag = Tag::identifier("id"); + c.bench_function("get_tag_kind", |bh| bh.iter(|| black_box(tag.kind()))); +} + +fn parse_p_tag(c: &mut Criterion) { + let tag = [ + "p", + "13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d", + ]; + c.bench_function("parse_p_tag", |bh| { + bh.iter(|| black_box(Tag::parse(tag)).unwrap()) + }); +} + +fn parse_p_standardized_tag(c: &mut Criterion) { + let tag = &[ + "p", + "13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d", + ]; + c.bench_function("parse_p_standardized_tag", |bh| { + bh.iter(|| black_box(TagStandard::parse(tag)).unwrap()) + }); +} + +fn parse_e_tag(c: &mut Criterion) { + let tag = [ + "e", + "378f145897eea948952674269945e88612420db35791784abf0616b4fed56ef7", + "wss://relay.damus.io", + ]; + c.bench_function("parse_e_tag", |bh| { + bh.iter(|| black_box(Tag::parse(tag)).unwrap()) + }); +} + +fn parse_e_standardized_tag(c: &mut Criterion) { + let tag = &[ + "e", + "378f145897eea948952674269945e88612420db35791784abf0616b4fed56ef7", + "wss://relay.damus.io", + ]; + c.bench_function("parse_e_standardized_tag", |bh| { + bh.iter(|| black_box(TagStandard::parse(tag)).unwrap()) + }); +} + +fn parse_a_tag(c: &mut Criterion) { + let tag = [ + "a", + "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", + "wss://relay.nostr.org", + ]; + c.bench_function("parse_a_tag", |bh| { + bh.iter(|| black_box(Tag::parse(tag)).unwrap()) + }); +} + +fn parse_t_tag(c: &mut Criterion) { + let tag = ["t", "test"]; + c.bench_function("parse_t_tag", |bh| { + bh.iter(|| black_box(Tag::parse(tag)).unwrap()) + }); +} + +fn parse_a_standardized_tag(c: &mut Criterion) { + let tag = &[ + "a", + "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", + "wss://relay.nostr.org", + ]; + c.bench_function("parse_a_standardized_tag", |bh| { + bh.iter(|| black_box(TagStandard::parse(tag)).unwrap()) + }); +} + +pub fn benches(c: &mut Criterion) { + generate_keys(c); + + tags_dedup_10_tags(c); + tags_dedup_50_tags(c); + tags_dedup_100_tags(c); + tags_dedup_500_tags(c); + tags_dedup_1000_tags(c); + tags_dedup_2000_tags(c); + tags_dedup_4000_tags(c); + tags_push(c); + vec_tag_push(c); + tags_pop(c); + vec_tag_pop(c); + + get_tag_kind(c); + parse_p_tag(c); + parse_p_standardized_tag(c); + parse_e_tag(c); + parse_e_standardized_tag(c); + parse_a_tag(c); + parse_t_tag(c); + parse_a_standardized_tag(c); +} diff --git a/benches/src/types.rs b/benches/src/types.rs new file mode 100644 index 000000000..53702b16f --- /dev/null +++ b/benches/src/types.rs @@ -0,0 +1,54 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2025 Rust Nostr Developers +// Distributed under the MIT software license + +use std::hint::black_box; + +use criterion::Criterion; +use nostr::types::{RelayUrl, Timestamp}; + +const LOCAL_URL: &str = "ws://127.0.0.1:7777"; +const CLEARNET_URL: &str = "wss://relay.damus.io"; +const ONION_URL: &str = "ws://oxtrdevav64z64yb7x6rjg4ntzqjhedm5b5zjqulugknhzr46ny2qbad.onion"; + +fn timestamp_to_human_datetime(c: &mut Criterion) { + let timestamp = Timestamp::from(1682060685); + + c.bench_function("timestamp_to_human_datetime", |bh| { + bh.iter(|| { + black_box(timestamp.to_human_datetime()); + }) + }); +} + +fn parse_local_relay_url(c: &mut Criterion) { + c.bench_function("parse_local_relay_url", |bh| { + bh.iter(|| { + black_box(RelayUrl::parse(LOCAL_URL)).unwrap(); + }) + }); +} + +fn parse_clearnet_relay_url(c: &mut Criterion) { + c.bench_function("parse_clearnet_relay_url", |bh| { + bh.iter(|| { + black_box(RelayUrl::parse(CLEARNET_URL)).unwrap(); + }) + }); +} + +fn parse_onion_relay_url(c: &mut Criterion) { + c.bench_function("parse_onion_relay_url", |bh| { + bh.iter(|| { + black_box(RelayUrl::parse(ONION_URL)).unwrap(); + }) + }); +} + +pub fn benches(c: &mut Criterion) { + timestamp_to_human_datetime(c); + + parse_local_relay_url(c); + parse_clearnet_relay_url(c); + parse_onion_relay_url(c); +} diff --git a/crates/nostr/Cargo.toml b/crates/nostr/Cargo.toml index 8bb43a4dd..3691d1852 100644 --- a/crates/nostr/Cargo.toml +++ b/crates/nostr/Cargo.toml @@ -138,6 +138,3 @@ required-features = ["std", "rand", "os-rng", "nip98"] [[example]] name = "parser" required-features = ["std"] - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bench)'] } diff --git a/crates/nostr/src/event/builder.rs b/crates/nostr/src/event/builder.rs index 0ccc55730..ace8e5268 100644 --- a/crates/nostr/src/event/builder.rs +++ b/crates/nostr/src/event/builder.rs @@ -2359,19 +2359,3 @@ mod tests { ); } } - -#[cfg(bench)] -#[cfg(all(feature = "std", feature = "os-rng"))] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn builder_to_event(bh: &mut Bencher) { - let keys = Keys::generate(); - bh.iter(|| { - black_box(EventBuilder::text_note("hello").sign_with_keys(&keys)).unwrap(); - }); - } -} diff --git a/crates/nostr/src/event/id.rs b/crates/nostr/src/event/id.rs index 753970607..35d2ee003 100644 --- a/crates/nostr/src/event/id.rs +++ b/crates/nostr/src/event/id.rs @@ -230,18 +230,3 @@ mod tests { assert!(!id.check_pow(25)); } } - -#[cfg(bench)] -mod benches { - use super::*; - use crate::test::{Bencher, black_box}; - - const ID: &str = "2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45"; - - #[bench] - pub fn parse_event_id_from_hex(bh: &mut Bencher) { - bh.iter(|| { - black_box(EventId::from_hex(ID)).unwrap(); - }); - } -} diff --git a/crates/nostr/src/event/kind.rs b/crates/nostr/src/event/kind.rs index de3a2b8bd..4dfd54b90 100644 --- a/crates/nostr/src/event/kind.rs +++ b/crates/nostr/src/event/kind.rs @@ -415,24 +415,3 @@ mod tests { assert_eq!(kind, Kind::Custom(u16::MAX)); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn parse_ephemeral_kind(bh: &mut Bencher) { - bh.iter(|| { - black_box(Kind::from(29_999)); - }); - } - - #[bench] - pub fn parse_kind(bh: &mut Bencher) { - bh.iter(|| { - black_box(Kind::from(0)); - }); - } -} diff --git a/crates/nostr/src/event/mod.rs b/crates/nostr/src/event/mod.rs index 8aa379689..62327d255 100644 --- a/crates/nostr/src/event/mod.rs +++ b/crates/nostr/src/event/mod.rs @@ -528,54 +528,3 @@ mod tests { assert!(!event.is_protected()); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn deserialize_event(bh: &mut Bencher) { - let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; - bh.iter(|| { - black_box(Event::from_json(json)).unwrap(); - }); - } - - #[bench] - pub fn serialize_event(bh: &mut Bencher) { - let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; - let event = Event::from_json(json).unwrap(); - bh.iter(|| { - black_box(event.as_json()); - }); - } - - #[bench] - pub fn event_check_pow(bh: &mut Bencher) { - let json = r#"{"id":"000006d11924b38e55275637c6401965c54f9ae05ffed89bce0edc1720984656","pubkey":"385c3a6ec0b9d57a4330dbd6284989be5bd00e41c535f9ca39b6ae7c521b81cd","created_at":1759497131,"kind":1,"tags":[["nonce","1180727","20"]],"content":"This is a Nostr message with embedded proof-of-work","sig":"0b216dfa714db2f146f9fa7cf20954c3fd5a2dabf69cd30ab58cf142a7ebe0fd3f4bc8e9c261245dabc0be8f942ec15d3fe3ce4dcbe81df01ceb4ced91739f52"}"#; - let event = Event::from_json(json).unwrap(); - bh.iter(|| { - black_box(event.check_pow(16)); - }); - } - - #[bench] - pub fn verify_event_id(bh: &mut Bencher) { - let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; - let event = Event::from_json(json).unwrap(); - bh.iter(|| { - black_box(event.verify_id()); - }); - } - - #[bench] - pub fn verify_event_sig(bh: &mut Bencher) { - let json = r#"{"content":"uRuvYr585B80L6rSJiHocw==?iv=oh6LVqdsYYol3JfFnXTbPA==","created_at":1640839235,"id":"2be17aa3031bdcb006f0fce80c146dea9c1c0268b0af2398bb673365c6444d45","kind":4,"pubkey":"f86c44a2de95d9149b51c6a29afeabba264c18e2fa7c49de93424a0c56947785","sig":"a5d9290ef9659083c490b303eb7ee41356d8778ff19f2f91776c8dc4443388a64ffcf336e61af4c25c05ac3ae952d1ced889ed655b67790891222aaa15b99fdd","tags":[["p","13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d"]]}"#; - let event = Event::from_json(json).unwrap(); - bh.iter(|| { - black_box(event.verify_signature()); - }); - } -} diff --git a/crates/nostr/src/event/tag/list.rs b/crates/nostr/src/event/tag/list.rs index a9cceaed1..9d78f3c07 100644 --- a/crates/nostr/src/event/tag/list.rs +++ b/crates/nostr/src/event/tag/list.rs @@ -678,172 +678,3 @@ mod tests { tags.dedup(); } } - -#[cfg(bench)] -#[cfg(all(feature = "std", feature = "os-rng"))] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - use crate::RelayUrl; - use crate::key::Keys; - - fn generate_tags(n: usize) -> Tags { - let half = n / 2; - - let mut pubkeys = Vec::with_capacity(half); - - let mut tags = Vec::with_capacity(n); - - for _ in 0..half { - let keys = Keys::generate(); - - // Save pubkey - pubkeys.push(keys.public_key()); - - // Push simple p tag - tags.push(Tag::public_key(keys.public_key())); - } - - for pk in pubkeys.into_iter() { - // Push long p tag - let long_p_tag = Tag::from_standardized_without_cell(TagStandard::PublicKey { - public_key: pk, - relay_url: Some(RelayUrl::parse("wss://relay.damus.io").unwrap()), - uppercase: false, - alias: None, - }); - tags.push(long_p_tag) - } - - Tags::from_list(tags) - } - - #[bench] - pub fn tags_dedup_10_tags(bh: &mut Bencher) { - let mut tags = generate_tags(10); - - assert!(tags.len() == 10); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 5); - } - - #[bench] - pub fn tags_dedup_50_tags(bh: &mut Bencher) { - let mut tags = generate_tags(50); - - assert!(tags.len() == 50); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 25); - } - - #[bench] - pub fn tags_dedup_100_tags(bh: &mut Bencher) { - let mut tags = generate_tags(100); - - assert!(tags.len() == 100); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 50); - } - - #[bench] - pub fn tags_dedup_500_tags(bh: &mut Bencher) { - let mut tags = generate_tags(500); - - assert!(tags.len() == 500); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 250); - } - - #[bench] - pub fn tags_dedup_1000_tags(bh: &mut Bencher) { - let mut tags = generate_tags(1000); - - assert!(tags.len() == 1000); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 500); - } - - #[bench] - pub fn tags_dedup_2000_tags(bh: &mut Bencher) { - let mut tags = generate_tags(2000); - - assert!(tags.len() == 2000); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 1000); - } - - #[bench] - pub fn tags_dedup_4000_tags(bh: &mut Bencher) { - let mut tags = generate_tags(4000); - - assert!(tags.len() == 4000); - - bh.iter(|| { - black_box(tags.dedup()); - }); - - assert!(tags.len() == 2000); - } - - #[bench] - pub fn tags_push(bh: &mut Bencher) { - let mut tags = Tags::new(); - - bh.iter(|| { - black_box(tags.push(Tag::protected())); - }); - } - - #[bench] - pub fn vec_tag_push(bh: &mut Bencher) { - let mut tags = Vec::new(); - - bh.iter(|| { - black_box(tags.push(Tag::protected())); - }); - } - - #[bench] - pub fn tags_pop(bh: &mut Bencher) { - let mut tags = generate_tags(4000); - - bh.iter(|| { - black_box(tags.pop()); - }); - } - - #[bench] - pub fn vec_tag_pop(bh: &mut Bencher) { - let tags = generate_tags(4000); - let mut tags = tags.to_vec(); - - bh.iter(|| { - black_box(tags.pop()); - }); - } -} diff --git a/crates/nostr/src/event/tag/mod.rs b/crates/nostr/src/event/tag/mod.rs index fd418d69e..7c44a1713 100644 --- a/crates/nostr/src/event/tag/mod.rs +++ b/crates/nostr/src/event/tag/mod.rs @@ -789,96 +789,3 @@ mod tests { assert_eq!(Tag::hashtag("Nostr"), Tag::custom(TagKind::t(), ["nostr"])); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn get_tag_kind(bh: &mut Bencher) { - let tag = Tag::identifier("id"); - bh.iter(|| { - black_box(tag.kind()); - }); - } - - #[bench] - pub fn parse_p_tag(bh: &mut Bencher) { - let tag = [ - "p", - "13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d", - ]; - bh.iter(|| { - black_box(Tag::parse(tag)).unwrap(); - }); - } - - #[bench] - pub fn parse_p_standardized_tag(bh: &mut Bencher) { - let tag = &[ - "p", - "13adc511de7e1cfcf1c6b7f6365fb5a03442d7bcacf565ea57fa7770912c023d", - ]; - bh.iter(|| { - black_box(TagStandard::parse(tag)).unwrap(); - }); - } - - #[bench] - pub fn parse_e_tag(bh: &mut Bencher) { - let tag = [ - "e", - "378f145897eea948952674269945e88612420db35791784abf0616b4fed56ef7", - "wss://relay.damus.io", - ]; - bh.iter(|| { - black_box(Tag::parse(tag)).unwrap(); - }); - } - - #[bench] - pub fn parse_e_standardized_tag(bh: &mut Bencher) { - let tag = &[ - "e", - "378f145897eea948952674269945e88612420db35791784abf0616b4fed56ef7", - "wss://relay.damus.io", - ]; - bh.iter(|| { - black_box(TagStandard::parse(tag)).unwrap(); - }); - } - - #[bench] - pub fn parse_a_tag(bh: &mut Bencher) { - let tag = [ - "a", - "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", - "wss://relay.nostr.org", - ]; - bh.iter(|| { - black_box(Tag::parse(tag)).unwrap(); - }); - } - - #[bench] - pub fn parse_t_tag(bh: &mut Bencher) { - let tag = ["t", "test"]; - bh.iter(|| { - black_box(Tag::parse(tag)).unwrap(); - }); - } - - #[bench] - pub fn parse_a_standardized_tag(bh: &mut Bencher) { - let tag = &[ - "a", - "30023:a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919:ipsum", - "wss://relay.nostr.org", - ]; - bh.iter(|| { - black_box(TagStandard::parse(tag)).unwrap(); - }); - } -} diff --git a/crates/nostr/src/filter.rs b/crates/nostr/src/filter.rs index d32a02c62..0269df2f0 100644 --- a/crates/nostr/src/filter.rs +++ b/crates/nostr/src/filter.rs @@ -1336,49 +1336,3 @@ mod tests { assert!(filter.match_event(&event, MatchEventOptions::new())); } } - -#[cfg(bench)] -mod benches { - use core::str::FromStr; - - use secp256k1::schnorr::Signature; - use test::{Bencher, black_box}; - - use super::*; - use crate::{Tag, TagStandard}; - - #[bench] - pub fn filter_match_event(bh: &mut Bencher) { - // Event - let event = - Event::new( - EventId::from_hex("70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5") - .unwrap(), - PublicKey::from_hex("379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe") - .unwrap(), - Timestamp::from(1612809991), - Kind::TextNote, - [ - Tag::public_key(PublicKey::from_hex("b2d670de53b27691c0c3400225b65c35a26d06093bcc41f48ffc71e0907f9d4a").unwrap()), - Tag::public_key(PublicKey::from_hex("379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe").unwrap()), - Tag::event(EventId::from_hex("7469af3be8c8e06e1b50ef1caceba30392ddc0b6614507398b7d7daa4c218e96").unwrap()), - Tag::from_standardized(TagStandard::Kind { kind: Kind::TextNote, uppercase: false }), - ], - "#JoininBox is a minimalistic, security focused Linux environment for #JoinMarket with a terminal based graphical menu.\n\nnostr:npub14tq8m9ggnnn2muytj9tdg0q6f26ef3snpd7ukyhvrxgq33vpnghs8shy62 ๐Ÿ‘๐Ÿงก\n\nhttps://www.nobsbitcoin.com/joininbox-v0-8-0/", - Signature::from_str("273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502").unwrap(), - ); - - // Filter - let pk = - PublicKey::from_hex("b2d670de53b27691c0c3400225b65c35a26d06093bcc41f48ffc71e0907f9d4a") - .unwrap(); - let filter = Filter::new() - .pubkey(pk) - .search("linux") - .kind(Kind::TextNote); - - bh.iter(|| { - black_box(filter.match_event(&event, MatchEventOptions::new())); - }); - } -} diff --git a/crates/nostr/src/key/mod.rs b/crates/nostr/src/key/mod.rs index b74e354db..65b1c0219 100644 --- a/crates/nostr/src/key/mod.rs +++ b/crates/nostr/src/key/mod.rs @@ -380,18 +380,3 @@ mod tests { ); } } - -#[cfg(bench)] -#[cfg(all(feature = "std", feature = "os-rng"))] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn generate_keys(bh: &mut Bencher) { - bh.iter(|| { - black_box(Keys::generate()); - }); - } -} diff --git a/crates/nostr/src/key/public_key.rs b/crates/nostr/src/key/public_key.rs index 444aec7fa..3f1b7af80 100644 --- a/crates/nostr/src/key/public_key.rs +++ b/crates/nostr/src/key/public_key.rs @@ -230,66 +230,3 @@ mod tests { assert_eq!(&xonly, &expected); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - use crate::nips::nip19::ToBech32; - - const NIP21_URI: &str = "nostr:npub14f8usejl26twx0dhuxjh9cas7keav9vr0v8nvtwtrjqx3vycc76qqh9nsy"; - const HEX: &str = "aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4"; - const BECH32: &str = "npub14f8usejl26twx0dhuxjh9cas7keav9vr0v8nvtwtrjqx3vycc76qqh9nsy"; - - #[bench] - pub fn parse_public_key_nip21_uri(bh: &mut Bencher) { - bh.iter(|| { - black_box(PublicKey::parse(NIP21_URI)).unwrap(); - }); - } - - #[bench] - pub fn parse_public_key_hex(bh: &mut Bencher) { - bh.iter(|| { - black_box(PublicKey::parse(HEX)).unwrap(); - }); - } - - #[bench] - pub fn public_key_from_hex(bh: &mut Bencher) { - bh.iter(|| { - black_box(PublicKey::from_hex(HEX)).unwrap(); - }); - } - - #[bench] - pub fn parse_public_key_bech32(bh: &mut Bencher) { - bh.iter(|| { - black_box(PublicKey::parse(BECH32)).unwrap(); - }); - } - - #[bench] - pub fn public_key_from_bech32(bh: &mut Bencher) { - bh.iter(|| { - black_box(PublicKey::from_bech32(BECH32)).unwrap(); - }); - } - - #[bench] - pub fn public_key_to_hex(bh: &mut Bencher) { - let public_key = PublicKey::from_hex(HEX).unwrap(); - bh.iter(|| { - black_box(public_key.to_bech32()).unwrap(); - }); - } - - #[bench] - pub fn public_key_to_bech32(bh: &mut Bencher) { - let public_key = PublicKey::from_hex(HEX).unwrap(); - bh.iter(|| { - black_box(public_key.to_bech32()).unwrap(); - }); - } -} diff --git a/crates/nostr/src/lib.rs b/crates/nostr/src/lib.rs index 560851d2e..d437b7832 100644 --- a/crates/nostr/src/lib.rs +++ b/crates/nostr/src/lib.rs @@ -9,15 +9,11 @@ #![warn(rustdoc::bare_urls)] #![allow(clippy::arc_with_non_send_sync)] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(bench, feature(test))] #![cfg_attr(all(feature = "std", feature = "os-rng", feature = "all-nips"), doc = include_str!("../README.md"))] #[cfg(not(any(feature = "std", feature = "alloc")))] compile_error!("at least one of the `std` or `alloc` features must be enabled"); -#[cfg(bench)] -extern crate test; - #[cfg(feature = "std")] #[macro_use] extern crate std; diff --git a/crates/nostr/src/message/relay.rs b/crates/nostr/src/message/relay.rs index 3d5269418..ec8a8cf7f 100644 --- a/crates/nostr/src/message/relay.rs +++ b/crates/nostr/src/message/relay.rs @@ -684,35 +684,3 @@ mod tests { ); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - fn bench_parse_machine_readable_prefix(bh: &mut Bencher) { - bh.iter(|| { - black_box(MachineReadablePrefix::parse( - "blocked: you are banned from posting here", - )); - }) - } - - #[bench] - pub fn parse_ok_relay_message(bh: &mut Bencher) { - let json: &str = r#"["OK", "70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5", true, "pow: difficulty 25>=24"]"#; - bh.iter(|| { - black_box(RelayMessage::from_json(&json)).unwrap(); - }); - } - - #[bench] - pub fn parse_event_relay_message(bh: &mut Bencher) { - let json: &str = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502"}]"#; - bh.iter(|| { - black_box(RelayMessage::from_json(&json)).unwrap(); - }); - } -} diff --git a/crates/nostr/src/nips/nip01.rs b/crates/nostr/src/nips/nip01.rs index 321cbaf35..740b41649 100644 --- a/crates/nostr/src/nips/nip01.rs +++ b/crates/nostr/src/nips/nip01.rs @@ -621,19 +621,3 @@ mod tests { ) } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn parse_coordinate(bh: &mut Bencher) { - let coordinate: &str = - "30023:aa4fc8665f5696e33db7e1a572e3b0f5b3d615837b0f362dcb1c8068b098c7b4:ipsum"; - bh.iter(|| { - black_box(Coordinate::parse(coordinate)).unwrap(); - }); - } -} diff --git a/crates/nostr/src/nips/nip19.rs b/crates/nostr/src/nips/nip19.rs index 5e7464458..8178939bc 100644 --- a/crates/nostr/src/nips/nip19.rs +++ b/crates/nostr/src/nips/nip19.rs @@ -939,28 +939,3 @@ mod tests { assert!(event.author.is_none()); } } - -#[cfg(bench)] -mod benches { - use super::*; - use crate::test::{Bencher, black_box}; - - #[bench] - pub fn to_bech32_nevent(bh: &mut Bencher) { - let event_id = - EventId::from_hex("d94a3f4dd87b9a3b0bed183b32e916fa29c8020107845d1752d72697fe5309a5") - .unwrap(); - let public_key = - PublicKey::from_str("32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245") - .unwrap(); - let relays = [ - RelayUrl::parse("wss://r.x.com").unwrap(), - RelayUrl::parse("wss://djbas.sadkb.com").unwrap(), - ]; - let nip19_event = Nip19Event::new(event_id).author(public_key).relays(relays); - - bh.iter(|| { - black_box(nip19_event.to_bech32()).unwrap(); - }); - } -} diff --git a/crates/nostr/src/parser.rs b/crates/nostr/src/parser.rs index 55925f825..a5be68306 100644 --- a/crates/nostr/src/parser.rs +++ b/crates/nostr/src/parser.rs @@ -1477,39 +1477,3 @@ mod tests { ); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - const PARSER: NostrParser = NostrParser::new(); - - #[bench] - pub fn bench_parse_text_with_nostr_uris(bh: &mut Bencher) { - let text: &str = "I have never been very active in discussions but working on rust-nostr (at the time called nostr-rs-sdk) since September 2022 ๐Ÿฆ€ \n\nIf I remember correctly there were also nostr:nprofile1qqsqfyvdlsmvj0nakmxq6c8n0c2j9uwrddjd8a95ynzn9479jhlth3gpvemhxue69uhkv6tvw3jhytnwdaehgu3wwa5kuef0dec82c33w94xwcmdd3cxketedsux6ertwecrgues0pk8xdrew33h27pkd4unvvpkw3nkv7pe0p68gat58ycrw6ps0fenwdnvva48w0mzwfhkzerrv9ehg0t5wf6k2qgnwaehxw309ac82unsd3jhqct89ejhxtcpz4mhxue69uhhyetvv9ujuerpd46hxtnfduhsh8njvk and nostr:nprofile1qqswuyd9ml6qcxd92h6pleptfrcqucvvjy39vg4wx7mv9wm8kakyujgpypmhxue69uhkx6r0wf6hxtndd94k2erfd3nk2u3wvdhk6w35xs6z7qgwwaehxw309ahx7uewd3hkctcpypmhxue69uhkummnw3ezuetfde6kuer6wasku7nfvuh8xurpvdjj7a0nq40"; - - bh.iter(|| { - black_box(PARSER.parse(text).collect::>()); - }); - } - - #[bench] - pub fn bench_parse_text_with_urls(bh: &mut Bencher) { - let text: &str = "I've uses both the book and rustlings: https://github.com/rust-lang/rustlings/\n\nThere is also the \"Rust by example\" book: https://doc.rust-lang.org/rust-by-example/\n\nWhile you read the book, try to make projects from scratch (not just simple ones). At the end, writing code is the best way to learn it."; - - bh.iter(|| { - black_box(PARSER.parse(text).collect::>()); - }); - } - - #[bench] - pub fn bench_parse_text_with_hashtags(bh: &mut Bencher) { - let text: &str = "Hey #rust-nostr fans, can you enlighten me please:\nWhen I am calculating my Web of Trust I do the following:\n0. Create client with outbox model enabled\n1. Get my follows, mutes, reports in one fetch call\n2. Get follows, mutes, reports of my follows in another fetch call, using an authors filter that has all follows in it\n3. Calculate scores with my weights locally\n\nQuestion:\nWhy did step 2. take hours to complete?\n\nIt seems like it's trying to connect to loads of relays.\nMy guess is either I am doing sth horribly wrong or there is no smart relay set calculation for filters in the pool.\n\nIn ndk this calculation takes under 10 seconds to complete, even without any caching. It will first look at the filters and calculate a relay set that has all authors in it then does the fetching.\n\n#asknostr #rust"; - - bh.iter(|| { - black_box(PARSER.parse(text).collect::>()); - }); - } -} diff --git a/crates/nostr/src/types/time.rs b/crates/nostr/src/types/time.rs index e88eb9367..6beea2836 100644 --- a/crates/nostr/src/types/time.rs +++ b/crates/nostr/src/types/time.rs @@ -295,18 +295,3 @@ mod tests { ); } } - -#[cfg(bench)] -mod benches { - use test::{Bencher, black_box}; - - use super::*; - - #[bench] - pub fn timestamp_to_human_datetime(bh: &mut Bencher) { - let timestamp = Timestamp::from(1682060685); - bh.iter(|| { - black_box(timestamp.to_human_datetime()); - }); - } -} diff --git a/crates/nostr/src/types/url.rs b/crates/nostr/src/types/url.rs index 4ee39416c..e32ad9522 100644 --- a/crates/nostr/src/types/url.rs +++ b/crates/nostr/src/types/url.rs @@ -485,34 +485,3 @@ mod tests { assert_eq!(url.domain(), None); } } - -#[cfg(bench)] -mod benches { - use super::*; - use crate::test::{Bencher, black_box}; - - const LOCAL_URL: &str = "ws://127.0.0.1:7777"; - const CLEARNET_URL: &str = "wss://relay.damus.io"; - const ONION_URL: &str = "ws://oxtrdevav64z64yb7x6rjg4ntzqjhedm5b5zjqulugknhzr46ny2qbad.onion"; - - #[bench] - pub fn parse_local_relay_url(bh: &mut Bencher) { - bh.iter(|| { - black_box(RelayUrl::parse(LOCAL_URL)).unwrap(); - }); - } - - #[bench] - pub fn parse_clearnet_relay_url(bh: &mut Bencher) { - bh.iter(|| { - black_box(RelayUrl::parse(CLEARNET_URL)).unwrap(); - }); - } - - #[bench] - pub fn parse_onion_relay_url(bh: &mut Bencher) { - bh.iter(|| { - black_box(RelayUrl::parse(ONION_URL)).unwrap(); - }); - } -} diff --git a/database/nostr-database/Cargo.toml b/database/nostr-database/Cargo.toml index e7e6b9c61..bc2ffe2d2 100644 --- a/database/nostr-database/Cargo.toml +++ b/database/nostr-database/Cargo.toml @@ -23,6 +23,3 @@ flatbuf = ["dep:flatbuffers"] btreecap.workspace = true flatbuffers = { version = "25.12", optional = true } nostr = { workspace = true, features = ["std"] } - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bench)'] } diff --git a/database/nostr-database/src/flatbuffers/mod.rs b/database/nostr-database/src/flatbuffers/mod.rs index 979114d08..1f0f1334c 100644 --- a/database/nostr-database/src/flatbuffers/mod.rs +++ b/database/nostr-database/src/flatbuffers/mod.rs @@ -209,42 +209,3 @@ impl<'a> FlatBufferDecodeBorrowed<'a> for EventBorrow<'a> { }) } } - -#[cfg(bench)] -mod benches { - use super::*; - use crate::test::{Bencher, black_box}; - - #[bench] - pub fn bench_decode_flatbuf_event_borrow(bh: &mut Bencher) { - let json = r#"{ - "content": "+", - "created_at": 1716508454, - "id": "3e9e9c2fbf263590860a9c60a7de6b0d166230a5a15aa8dcdb70f537cec9807a", - "kind": 7, - "pubkey": "3bbddb5c7233ad993b41cb639e63122120f391b8580a9b83aae33c648230e0a3", - "sig": "3f2ba6d713e4851500b81de2d2ef44b72f1eff061898bf8488e74f7e4ed141b0dadab4c3a9c6b237f3a6db83171bd41eafd7ab973f6fb067a4305e95abeadeee", - "tags": [ - [ - "e", - "e1e786c60ed884b6e784712aaf70e63b848b7403ef651b52b701d87739ea1808", - "", - "", - "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9" - ], - [ - "p", - "04c915daefee38317fa734444acee390a8269fe5810b2241e5e6dd343dfbecc9" - ] - ] - }"#; - let event = Event::from_json(json).unwrap(); - - let mut fbb = FlatBufferBuilder::new(); - let bytes = event.encode(&mut fbb); - - bh.iter(|| { - black_box(EventBorrow::decode(bytes)).unwrap(); - }); - } -} diff --git a/database/nostr-database/src/lib.rs b/database/nostr-database/src/lib.rs index 74cb91b32..c6a33d0d7 100644 --- a/database/nostr-database/src/lib.rs +++ b/database/nostr-database/src/lib.rs @@ -7,12 +7,8 @@ #![warn(missing_docs)] #![warn(rustdoc::bare_urls)] #![warn(clippy::large_futures)] -#![cfg_attr(bench, feature(test))] #![allow(clippy::mutable_key_type)] // TODO: remove when possible. Needed to suppress false positive for `BTreeSet` -#[cfg(bench)] -extern crate test; - use std::any::Any; use std::collections::HashMap; use std::fmt::Debug; diff --git a/justfile b/justfile index efb25af14..a1ebc37f6 100755 --- a/justfile +++ b/justfile @@ -47,6 +47,8 @@ coverage package='none': @echo @echo 'open {{ justfile_directory() }}/target/llvm-cov/html/index.html' -# Run benches (unstable) -bench: - RUSTFLAGS='--cfg=bench' cargo +nightly bench +# Run benches +bench benchmark='none': + RUSTFLAGS='--cfg=bench -Awarnings' cargo bench -p benches {{ if benchmark == 'none' { '' } else { '"'+benchmark+'"' } }} + @echo + @echo 'open {{ justfile_directory() }}/target/criterion/report/index.html' diff --git a/sdk/src/relay/inner.rs b/sdk/src/relay/inner.rs index 7846ce80d..f42360ea4 100644 --- a/sdk/src/relay/inner.rs +++ b/sdk/src/relay/inner.rs @@ -137,7 +137,7 @@ pub(super) struct AtomicPrivateData { } #[derive(Debug, Clone)] -pub(crate) struct InnerRelay { +pub struct InnerRelay { pub(super) url: RelayUrl, pub(super) atomic: Arc, pub(super) opts: RelayOptions, @@ -1082,7 +1082,7 @@ impl InnerRelay { } } - async fn handle_raw_relay_message( + pub async fn handle_raw_relay_message( &self, msg: &str, ) -> Result>, Error> { @@ -1791,46 +1791,18 @@ async fn close_ws(tx: &mut WebSocketSink) -> Result<(), Error> { } #[cfg(bench)] -mod benches { - use std::sync::LazyLock; - - use test::Bencher; - use tokio::runtime::Runtime; - - use super::*; - - static RUNTIME: LazyLock = LazyLock::new(|| Runtime::new().unwrap()); - - fn relay() -> InnerRelay { - let url = RelayUrl::parse("ws://localhost:8080").unwrap(); - let state = SharedState::default(); - let opts = RelayOptions::default(); - InnerRelay::new(url, state, opts) - } - - #[bench] - fn bench_handle_relay_msg_event(bh: &mut Bencher) { - let relay = relay(); - - let msg = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"273a9cd5d11455590f4359500bccb7a89428262b96b3ea87a756b770964472f8c3e87f5d5e64d8d2e859a71462a3f477b554565c4f2f326cb01dd7620db71502"}]"#; - - bh.iter(|| { - RUNTIME.block_on(async { - relay.handle_raw_relay_message(msg).await.unwrap(); - }); - }); - } - - #[bench] - fn bench_handle_relay_msg_invalid_event(bh: &mut Bencher) { - let relay = relay(); - - let msg = r#"["EVENT", "random_string", {"id":"70b10f70c1318967eddf12527799411b1a9780ad9c43858f5e5fcd45486a13a5","pubkey":"379e863e8357163b5bce5d2688dc4f1dcc2d505222fb8d74db600f30535dfdfe","created_at":1612809991,"kind":1,"tags":[],"content":"test","sig":"fa163f5cfb75d77d9b6269011872ee22b34fb48d23251e9879bb1e4ccbdd8aaaf4b6dc5f5084a65ef42c52fbcde8f3178bac3ba207de827ec513a6aa39fa684c"}]"#; - - bh.iter(|| { - RUNTIME.block_on(async { - let _ = relay.handle_raw_relay_message(msg).await; - }); - }); - } +pub fn create_relay() -> InnerRelay { + let url = RelayUrl::parse("ws://localhost:8080").unwrap(); + let builder = super::RelayBuilder::new(url); + let state: SharedState = SharedState::new( + builder.database, + builder.websocket_transport, + builder.signer, + builder.admit_policy, + false, + None, + ); + let opts = RelayOptions::default(); + let cap = RelayCapabilities::default(); + InnerRelay::new(builder.url, state, cap, opts) } diff --git a/sdk/src/relay/mod.rs b/sdk/src/relay/mod.rs index ff58128e0..1249d6e73 100644 --- a/sdk/src/relay/mod.rs +++ b/sdk/src/relay/mod.rs @@ -19,7 +19,10 @@ mod builder; mod capabilities; mod constants; mod error; +#[cfg(not(bench))] mod inner; +#[cfg(bench)] +pub mod inner; mod limits; mod notification; mod options;