Skip to content

seq: Directly write separator string, instead of using format #7562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 24, 2025

Conversation

drinkcat
Copy link
Contributor

Doing stdout.write_all(separator.as_bytes())? is quite a bit faster than using format to do the same operation: write!(stdout, "{separator}")?.

This speeds up by about 10% on simple cases.

We do the same for the terminator even though this has no measurable performance impact.


Integer increments (no point comparing with coreutils on that one, it's much faster):

$ cargo build -r -p uu_seq && taskset -c 0 hyperfine --warmup 3 -L seq target/release/seq,./seq-main "{seq} 1 1000000"
    Finished `release` profile [optimized] target(s) in 0.12s
Benchmark 1: target/release/seq 1 1000000
  Time (mean ± σ):     162.9 ms ±   2.4 ms    [User: 161.5 ms, System: 0.9 ms]
  Range (min … max):   160.4 ms … 167.7 ms    17 runs
 
Benchmark 2: ./seq-main 1 1000000
  Time (mean ± σ):     182.2 ms ±   4.6 ms    [User: 179.9 ms, System: 0.8 ms]
  Range (min … max):   178.6 ms … 198.5 ms    16 runs
  
Summary
  target/release/seq 1 1000000 ran
    1.12 ± 0.03 times faster than ./seq-main 1 1000000

Float increments, we were already faster than coreutils, we gain another 10%:

$ cargo build -r -p uu_seq && taskset -c 0 hyperfine --warmup 3 -L seq target/release/seq,./seq-main,seq "{seq} 1 1.1 1000000"
    Finished `release` profile [optimized] target(s) in 0.12s
Benchmark 1: target/release/seq 1 1.1 1000000
  Time (mean ± σ):     222.0 ms ±   1.8 ms    [User: 220.9 ms, System: 0.6 ms]
  Range (min … max):   219.9 ms … 225.0 ms    13 runs
 
Benchmark 2: ./seq-main 1 1.1 1000000
  Time (mean ± σ):     246.4 ms ±   5.9 ms    [User: 243.5 ms, System: 0.8 ms]
  Range (min … max):   241.3 ms … 262.7 ms    11 runs
 
Benchmark 3: seq 1 1.1 1000000
  Time (mean ± σ):     274.2 ms ±   6.3 ms    [User: 271.1 ms, System: 0.9 ms]
  Range (min … max):   267.7 ms … 290.0 ms    10 runs
 
Summary
  target/release/seq 1 1.1 1000000 ran
    1.11 ± 0.03 times faster than ./seq-main 1 1.1 1000000
    1.23 ± 0.03 times faster than seq 1 1.1 1000000

Doing `stdout.write_all(separator.as_bytes())?` is quite a bit
faster than using format to do the same operation:
`write!(stdout, "{separator}")?`.

This speeds up by about 10% on simple cases.

We do the same for the terminator even though this has no measurable
performance impact.
@drinkcat
Copy link
Contributor Author

(probably a good idea to grep the rest of the repo for that pattern...)

Copy link

GNU testsuite comparison:

Congrats! The gnu test tests/tail/inotify-dir-recreate is no longer failing!
Congrats! The gnu test tests/timeout/timeout is no longer failing!

@sylvestre
Copy link
Contributor

wahou, i wasn't expecting such difference

@sylvestre sylvestre merged commit 36231f7 into uutils:main Mar 24, 2025
68 checks passed
@@ -260,15 +260,15 @@ fn print_seq(
let mut is_first_iteration = true;
while !done_printing(&value, &increment, &last) {
if !is_first_iteration {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I also tried to move that test out of the loop. That makes no difference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants