From ebba36de4b0e659cd7a93862ee5268fc412f93d7 Mon Sep 17 00:00:00 2001 From: Sachymetsu Date: Tue, 22 Sep 2026 11:14:43 +0200 Subject: [PATCH] Nailkov benchmarking & chain iterator fixes --- Cargo.lock | 285 +++++++++++++++++++++++++++ Cargo.toml | 6 + crates/nailbody/Cargo.toml | 3 + crates/nailbox/Cargo.toml | 3 + crates/nailcancel/Cargo.toml | 3 + crates/nailconfig/Cargo.toml | 3 + crates/nailfv/Cargo.toml | 3 + crates/nailgen/Cargo.toml | 3 + crates/nailgen/src/lib.rs | 21 -- crates/nailip/Cargo.toml | 3 + crates/nailkov/Cargo.toml | 12 ++ crates/nailkov/benches/generation.rs | 46 +++++ crates/nailkov/src/distribution.rs | 3 +- crates/nailkov/src/lib.rs | 63 +++--- crates/nailloader/Cargo.toml | 3 + crates/nailnet/Cargo.toml | 3 + crates/nailotel/Cargo.toml | 3 + crates/nailrater/Cargo.toml | 3 + crates/nailresponder/Cargo.toml | 3 + crates/nailrng/Cargo.toml | 3 + crates/nailrt/Cargo.toml | 3 + crates/nailserve/Cargo.toml | 3 + crates/nailservice/Cargo.toml | 3 + crates/nailspicy/Cargo.toml | 3 + crates/nailstate/Cargo.toml | 3 + crates/nailtrace/Cargo.toml | 3 + 26 files changed, 443 insertions(+), 50 deletions(-) create mode 100644 crates/nailkov/benches/generation.rs diff --git a/Cargo.lock b/Cargo.lock index 5446bdd..f4d9741 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,12 +26,33 @@ 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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + [[package]] name = "anyhow" version = "1.0.104" @@ -115,6 +136,12 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.4.7" @@ -150,6 +177,58 @@ dependencies = [ "rand_core 0.10.1", ] +[[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.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + [[package]] name = "cmake" version = "0.1.58" @@ -204,6 +283,60 @@ dependencies = [ "libc", ] +[[package]] +name = "criterion" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "950046b2aa2492f9a536f5f4f9a3de7b9e2476e575e05bd6c333371add4d98f3" +dependencies = [ + "alloca", + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "page_size", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d80a2f4f5b554395e47b5d8305bc3d27813bacb73493eb1001e8f76dae29ea" +dependencies = [ + "cast", + "itertools 0.13.0", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.23" @@ -216,6 +349,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40a998414a3656e7a11ca59d55598ce7df58daafd742e783844e80bbd8d500dd" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "ctrlc" version = "3.5.2" @@ -496,6 +635,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.16.1" @@ -638,6 +788,15 @@ dependencies = [ "hashbrown 0.17.1", ] +[[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" @@ -861,11 +1020,13 @@ dependencies = [ name = "nailkov" version = "0.1.0" dependencies = [ + "criterion", "crossbeam-utils", "estr", "hashbrown 0.17.1", "indexmap", "itertools 0.15.0", + "nailrng", "rand 0.10.2", "rand_distr", "rapidhash", @@ -1139,6 +1300,12 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "opentelemetry" version = "0.32.0" @@ -1238,6 +1405,16 @@ version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8" +[[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" @@ -1311,6 +1488,34 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" +[[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 = "portable-atomic" version = "1.15.0" @@ -1454,6 +1659,26 @@ dependencies = [ "rustversion", ] +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +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" @@ -1463,6 +1688,18 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + [[package]] name = "regex-automata" version = "0.4.18" @@ -1504,6 +1741,15 @@ version = "5.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08ae9d01b806e889f90d47e13c18fb95edd95a2222b42eee5e671679bc3476d7" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scc" version = "3.8.8" @@ -1684,6 +1930,16 @@ dependencies = [ "cfg-if", ] +[[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 = "tokio" version = "1.53.1" @@ -1973,6 +2229,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2042,6 +2308,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web-sys" +version = "0.3.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" @@ -2068,6 +2344,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 243fc12..5c83f72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,6 +73,7 @@ workspace = true [[bin]] path = "src/main.rs" name = "nailpit" +bench = false [features] default = ["custom_alloc"] @@ -91,6 +92,11 @@ nailloader = { path = "crates/nailloader" } color-eyre.workspace = true mimalloc-safe = { version = "0.1.66", optional = true, features = ["v3"] } +[profile.bench] +lto = true +codegen-units = 1 +debug = false + [profile.release] codegen-units = 1 lto = "fat" diff --git a/crates/nailbody/Cargo.toml b/crates/nailbody/Cargo.toml index 10a2c9c..e69999f 100644 --- a/crates/nailbody/Cargo.toml +++ b/crates/nailbody/Cargo.toml @@ -14,3 +14,6 @@ hyper.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailbox/Cargo.toml b/crates/nailbox/Cargo.toml index 1af5bcd..be5dbcc 100644 --- a/crates/nailbox/Cargo.toml +++ b/crates/nailbox/Cargo.toml @@ -11,3 +11,6 @@ rust-version.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailcancel/Cargo.toml b/crates/nailcancel/Cargo.toml index c3cadfb..02bf009 100644 --- a/crates/nailcancel/Cargo.toml +++ b/crates/nailcancel/Cargo.toml @@ -17,3 +17,6 @@ futures-lite.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailconfig/Cargo.toml b/crates/nailconfig/Cargo.toml index f9c0fb7..46ae10d 100644 --- a/crates/nailconfig/Cargo.toml +++ b/crates/nailconfig/Cargo.toml @@ -15,3 +15,6 @@ serde.workspace = true nailbox = { path = "../nailbox" } config = { version = "0.15.11", default-features = false, features = ["toml"] } color-eyre.workspace = true + +[lib] +bench = false diff --git a/crates/nailfv/Cargo.toml b/crates/nailfv/Cargo.toml index 528fca7..5bbe740 100644 --- a/crates/nailfv/Cargo.toml +++ b/crates/nailfv/Cargo.toml @@ -15,3 +15,6 @@ winnow.workspace = true [dev-dependencies] color-eyre.workspace = true + +[lib] +bench = false diff --git a/crates/nailgen/Cargo.toml b/crates/nailgen/Cargo.toml index 107509d..6d93353 100644 --- a/crates/nailgen/Cargo.toml +++ b/crates/nailgen/Cargo.toml @@ -29,3 +29,6 @@ tracing.workspace = true tracing-futures.workspace = true tokio.workspace = true winnow.workspace = true + +[lib] +bench = false diff --git a/crates/nailgen/src/lib.rs b/crates/nailgen/src/lib.rs index a7b8b91..2a051f0 100644 --- a/crates/nailgen/src/lib.rs +++ b/crates/nailgen/src/lib.rs @@ -277,27 +277,6 @@ impl Stream for MarkovStream { } } -// impl hyper::body::Body for MarkovStream { -// type Data = Bytes; -// type Error = Infallible; - -// fn poll_frame( -// self: Pin<&mut Self>, -// cx: &mut Context<'_>, -// ) -> Poll, Self::Error>>> { -// match self.poll_next(cx) { -// Poll::Ready(Some(bytes)) => Poll::Ready(Some(Ok(Frame::data(bytes)))), -// Poll::Ready(None) => Poll::Ready(None), -// Poll::Pending => Poll::Pending, -// } -// } - -// #[inline] -// fn is_end_stream(&self) -> bool { -// matches!(&self.state, GeneratorState::Finished) -// } -// } - impl MarkovGen { pub fn new(input: impl AsRef) -> Result { let file = std::fs::read_to_string(input.as_ref())?; diff --git a/crates/nailip/Cargo.toml b/crates/nailip/Cargo.toml index 1f5fbba..39bcb8c 100644 --- a/crates/nailip/Cargo.toml +++ b/crates/nailip/Cargo.toml @@ -14,3 +14,6 @@ hyper.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailkov/Cargo.toml b/crates/nailkov/Cargo.toml index 79cd831..3c1ab68 100644 --- a/crates/nailkov/Cargo.toml +++ b/crates/nailkov/Cargo.toml @@ -21,3 +21,15 @@ tracing.workspace = true indexmap.workspace = true estr = "2.0.0" crossbeam-utils = "0.8.21" + +[dev-dependencies] +criterion = { version ="0.8.2", features = ["html_reports"] } +nailrng = { path = "../nailrng" } + +[lib] +bench = false + +[[bench]] +name = "generation" +path = "benches/generation.rs" +harness = false diff --git a/crates/nailkov/benches/generation.rs b/crates/nailkov/benches/generation.rs new file mode 100644 index 0000000..0a84bfe --- /dev/null +++ b/crates/nailkov/benches/generation.rs @@ -0,0 +1,46 @@ +use std::time::Duration; + +use criterion::{BenchmarkId, Criterion, PlotConfiguration, Throughput, criterion_main}; +use nailkov::{NailKov, NailKovIter}; +use nailrng::FastRng; + +static TEXT: &str = include_str!("moby.txt"); + +fn output_slop<'a>(slopper: NailKovIter<'a, FastRng>, amount: usize) -> String { + slopper.take(amount).map(|token| token.as_str()).collect() +} + +fn garbage_benchmark(c: &mut Criterion) { + c.bench_function("training", |b| { + b.iter_with_large_drop(|| NailKov::from_input(TEXT).unwrap()); + }); + + const LENGTHS: &[usize] = &[ + 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, + ]; + + let kovkov = NailKov::from_input(TEXT).unwrap(); + + let mut g = c.benchmark_group("generation"); + g.plot_config(PlotConfiguration::default().summary_scale(criterion::AxisScale::Logarithmic)); + + for length in LENGTHS { + g.throughput(Throughput::Elements(*length as u64)); + g.bench_with_input(BenchmarkId::from_parameter(length), length, |b, &l| { + let mut rng = FastRng::default(); + b.iter_with_large_drop(|| output_slop(kovkov.generate_tokens(&mut rng), l)); + }); + } + + g.finish(); +} + +pub fn benches() { + let mut criterion: Criterion<_> = Criterion::default() + .measurement_time(Duration::from_secs(10)) + .configure_from_args(); + + garbage_benchmark(&mut criterion); +} + +criterion_main!(benches); diff --git a/crates/nailkov/src/distribution.rs b/crates/nailkov/src/distribution.rs index a80b995..b8c4bdb 100644 --- a/crates/nailkov/src/distribution.rs +++ b/crates/nailkov/src/distribution.rs @@ -27,6 +27,7 @@ impl Distribution for TokenWeights { /// Builder for [`TokenWeights`]. #[derive(Clone, Debug)] +#[repr(transparent)] pub struct TokenWeightsBuilder { /// Counts how many times a token is likely to appear. occurrences: IndexMap, @@ -40,7 +41,7 @@ impl TokenWeightsBuilder { } /// Creates a weighted distribution for the likelihood of tokens to appear. - pub fn build(self) -> Result { + pub fn finish(self) -> Result { let (choices, counts): (Vec<_>, Vec<_>) = self.occurrences.into_iter().unzip(); if choices.is_empty() { diff --git a/crates/nailkov/src/lib.rs b/crates/nailkov/src/lib.rs index ca0df47..573a189 100644 --- a/crates/nailkov/src/lib.rs +++ b/crates/nailkov/src/lib.rs @@ -23,10 +23,12 @@ use unicode_segmentation::UnicodeSegmentation; /// `nailkov` relies on `estr`'s precomputed hashes, so we avoid /// hashing ourselves and can just use the precomputed hashes instead. type TokenHasher = BuildHasherDefault; +type TokenDistributions = IndexMap; #[derive(Clone, Debug)] +#[repr(transparent)] pub struct NailKov { - chain: CachePadded>, + chain: CachePadded, } pub struct NailKovIter<'a, R: Rng> { @@ -40,7 +42,17 @@ impl Iterator for NailKovIter<'_, R> { #[inline] fn next(&mut self) -> Option { - let dist = self.markov.chain.get(&self.prev)?; + let dist = loop { + match self.markov.chain.get(&self.prev) { + Some(weights) => break weights, + None => { + // Restart the chain if the pair hits an end point with + // a new starting token pair. + self.prev = self.markov.select_pair(self.rng); + continue; + } + } + }; let next_token = dist.sample(&mut self.rng); @@ -51,24 +63,29 @@ impl Iterator for NailKovIter<'_, R> { } impl NailKov { + fn select_pair(&self, rng: &mut R) -> TokenPair { + // A markov chain that was successfully built is never empty, so + // it will always return with a value, making unwrapping it safe to do. + self.chain.keys().choose(rng).copied().unwrap() + } + #[inline] pub fn generate_tokens<'a, R: Rng>(&'a self, rng: &'a mut R) -> NailKovIter<'a, R> { NailKovIter { - // A markov chain that was successfully built is never empty, so - // it will always return with a value, making unwrapping it safe to do. - prev: self.chain.keys().choose(rng).copied().unwrap(), + prev: self.select_pair(rng), markov: self, rng, } } -} -impl NailKov { pub fn from_input(input: &str) -> Result { - NailBuilder::new(TokenHasher::new()).with_input(input) + NailBuilder::new(TokenHasher::new()) + .feed_str(input)? + .finish() } } +#[repr(transparent)] struct NailBuilder { chain: IndexMap, } @@ -80,24 +97,16 @@ impl NailBuilder { } } - fn with_input(self, input: &str) -> Result { - self.feed_str(input)?.build() - } - - fn build(self) -> Result { + fn finish(self) -> Result { if self.chain.is_empty() { return Err(NailError::EmptyInput); } - let chain: IndexMap = self + let chain = self .chain .into_iter() - .flat_map(|(pair, dist)| { - dist.build() - .inspect_err(|err| tracing::error!("Weight error {pair:?}: {err}")) - .map(|build| (pair, build)) - }) - .collect(); + .map(|(pair, builder)| builder.finish().map(|weights| (pair, weights))) + .collect::>()?; if chain.is_empty() { return Err(NailError::EmptyInput); @@ -110,16 +119,14 @@ impl NailBuilder { /// Add the occurrence of `next` following `prev`. fn add_token_pair(&mut self, prev: TokenPair, next: Token) { - match self.chain.get_mut(&prev) { - Some(builder) => { - builder.add(next); - } - None => { + self.chain + .entry(prev) + .and_modify(|builder| builder.add(next)) + .or_insert_with(|| { let mut builder = TokenWeightsBuilder::new(); builder.add(next); - self.chain.insert(prev, builder); - } - } + builder + }); } fn feed_str(self, content: &str) -> Result { diff --git a/crates/nailloader/Cargo.toml b/crates/nailloader/Cargo.toml index fee0f58..9657613 100644 --- a/crates/nailloader/Cargo.toml +++ b/crates/nailloader/Cargo.toml @@ -18,3 +18,6 @@ glob = "0.3.2" [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailnet/Cargo.toml b/crates/nailnet/Cargo.toml index 4d108ae..6f18037 100644 --- a/crates/nailnet/Cargo.toml +++ b/crates/nailnet/Cargo.toml @@ -14,3 +14,6 @@ tokio.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailotel/Cargo.toml b/crates/nailotel/Cargo.toml index e8100a1..95764f4 100644 --- a/crates/nailotel/Cargo.toml +++ b/crates/nailotel/Cargo.toml @@ -26,3 +26,6 @@ opentelemetry-appender-tracing = { version = "0.32", features = [ [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailrater/Cargo.toml b/crates/nailrater/Cargo.toml index 87e0f89..2177f63 100644 --- a/crates/nailrater/Cargo.toml +++ b/crates/nailrater/Cargo.toml @@ -29,3 +29,6 @@ rapidhash.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailresponder/Cargo.toml b/crates/nailresponder/Cargo.toml index e415ebd..d46b722 100644 --- a/crates/nailresponder/Cargo.toml +++ b/crates/nailresponder/Cargo.toml @@ -20,3 +20,6 @@ matchit = "0.9.2" [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailrng/Cargo.toml b/crates/nailrng/Cargo.toml index d2a82ce..0c2a66b 100644 --- a/crates/nailrng/Cargo.toml +++ b/crates/nailrng/Cargo.toml @@ -14,3 +14,6 @@ wyrand.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailrt/Cargo.toml b/crates/nailrt/Cargo.toml index 7490d6f..ea0f0f3 100644 --- a/crates/nailrt/Cargo.toml +++ b/crates/nailrt/Cargo.toml @@ -24,3 +24,6 @@ tracing.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailserve/Cargo.toml b/crates/nailserve/Cargo.toml index 160b746..e4bfe37 100644 --- a/crates/nailserve/Cargo.toml +++ b/crates/nailserve/Cargo.toml @@ -27,3 +27,6 @@ futures-concurrency.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailservice/Cargo.toml b/crates/nailservice/Cargo.toml index 7a3e59f..9f2a4d2 100644 --- a/crates/nailservice/Cargo.toml +++ b/crates/nailservice/Cargo.toml @@ -17,3 +17,6 @@ pin-project-lite.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailspicy/Cargo.toml b/crates/nailspicy/Cargo.toml index b6947a2..a1af631 100644 --- a/crates/nailspicy/Cargo.toml +++ b/crates/nailspicy/Cargo.toml @@ -17,3 +17,6 @@ tracing.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailstate/Cargo.toml b/crates/nailstate/Cargo.toml index 7caf876..8038b38 100644 --- a/crates/nailstate/Cargo.toml +++ b/crates/nailstate/Cargo.toml @@ -17,3 +17,6 @@ rand.workspace = true [lints] workspace = true + +[lib] +bench = false diff --git a/crates/nailtrace/Cargo.toml b/crates/nailtrace/Cargo.toml index 356267d..0fa6afb 100644 --- a/crates/nailtrace/Cargo.toml +++ b/crates/nailtrace/Cargo.toml @@ -24,3 +24,6 @@ uuid = { version = "1.18", features = ["v7", "fast-rng"] } [lints] workspace = true + +[lib] +bench = false -- 2.51.2