shuf: perf: Use itoa for integer formatting

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.
This commit is contained in:
Jan Verbeek
2025-03-26 10:34:54 +01:00
parent 6e63312eba
commit 3017ddad9e
5 changed files with 8 additions and 20 deletions
+1
View File
@@ -38,6 +38,7 @@ getrandom
globset
indicatif
itertools
itoa
iuse
langid
lscolors
Generated
+1
View File
@@ -3867,6 +3867,7 @@ dependencies = [
"clap",
"codspeed-divan-compat",
"fluent",
"itoa",
"rand 0.9.2",
"rand_core 0.9.5",
"uucore",
+1
View File
@@ -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 = [
+1
View File
@@ -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 }
+4 -20
View File
@@ -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())
}
}