From 3017ddad9e94bdb2d7dadc91c5e20758cffb5a5f Mon Sep 17 00:00:00 2001 From: Jan Verbeek Date: Wed, 26 Mar 2025 10:34:54 +0100 Subject: [PATCH] shuf: perf: Use itoa for integer formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gives a 1.8× speedup over a stdlib formatted write for `shuf -r -n1000000 -i1-1024`. The original version of this commit replaced a formatted write, but before it got merged main received optimized manual formatting from another PR. The speedup of itoa over the manual write is around 1.1×, much less dramatic. --- .../workspace.wordlist.txt | 1 + Cargo.lock | 1 + Cargo.toml | 1 + src/uu/shuf/Cargo.toml | 1 + src/uu/shuf/src/shuf.rs | 24 ++++--------------- 5 files changed, 8 insertions(+), 20 deletions(-) diff --git a/.vscode/cspell.dictionaries/workspace.wordlist.txt b/.vscode/cspell.dictionaries/workspace.wordlist.txt index 28c468d4f..30d2bd3e0 100644 --- a/.vscode/cspell.dictionaries/workspace.wordlist.txt +++ b/.vscode/cspell.dictionaries/workspace.wordlist.txt @@ -38,6 +38,7 @@ getrandom globset indicatif itertools +itoa iuse langid lscolors diff --git a/Cargo.lock b/Cargo.lock index 5450edf53..c5e5d61dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3867,6 +3867,7 @@ dependencies = [ "clap", "codspeed-divan-compat", "fluent", + "itoa", "rand 0.9.2", "rand_core 0.9.5", "uucore", diff --git a/Cargo.toml b/Cargo.toml index 2f57496a5..d3eee72cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -335,6 +335,7 @@ icu_locale = "2.0.0" icu_provider = "2.0.0" indicatif = "0.18.0" itertools = "0.14.0" +itoa = "1.0.15" jiff = "0.2.18" libc = "0.2.172" lscolors = { version = "0.21.0", default-features = false, features = [ diff --git a/src/uu/shuf/Cargo.toml b/src/uu/shuf/Cargo.toml index 26a270b88..135dc29f4 100644 --- a/src/uu/shuf/Cargo.toml +++ b/src/uu/shuf/Cargo.toml @@ -19,6 +19,7 @@ path = "src/shuf.rs" [dependencies] clap = { workspace = true } +itoa = { workspace = true } rand = { workspace = true } rand_core = { workspace = true } uucore = { workspace = true } diff --git a/src/uu/shuf/src/shuf.rs b/src/uu/shuf/src/shuf.rs index 1cc444283..cc04a3068 100644 --- a/src/uu/shuf/src/shuf.rs +++ b/src/uu/shuf/src/shuf.rs @@ -340,26 +340,10 @@ impl Writable for &OsStr { impl Writable for usize { fn write_all_to(&self, output: &mut impl OsWrite) -> Result<(), Error> { - let mut n = *self; - - // Handle the zero case explicitly - if n == 0 { - return output.write_all(b"0"); - } - - // Maximum number of digits for u64 is 20 (18446744073709551615) - let mut buf = [0u8; 20]; - let mut i = 20; - - // Write digits from right to left - while n > 0 { - i -= 1; - buf[i] = b'0' + (n % 10) as u8; - n /= 10; - } - - // Write the relevant part of the buffer to output - output.write_all(&buf[i..]) + // The itoa crate is surprisingly much more efficient than a formatted write. + // It speeds up `shuf -r -n1000000 -i1-1024` by 1.8×. + let mut buf = itoa::Buffer::new(); + output.write_all(buf.format(*self).as_bytes()) } }