mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #7485 from drinkcat/seq-buffered
seq: Buffer writes to stdout
This commit is contained in:
commit
09f4e60e93
2 changed files with 35 additions and 4 deletions
|
@ -19,7 +19,38 @@ Finally, you can compare the performance of the two versions of `seq`
|
||||||
by running, for example,
|
by running, for example,
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
hyperfine "seq 1000000" "target/release/seq 1000000"
|
hyperfine -L seq seq,target/release/seq "{seq} 1000000"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Interesting test cases
|
||||||
|
|
||||||
|
Performance characteristics may vary a lot depending on the parameters,
|
||||||
|
and if custom formatting is required. In particular, it does appear
|
||||||
|
that the GNU implementation is heavily optimized for positive integer
|
||||||
|
outputs (which is probably the most common use case for `seq`).
|
||||||
|
|
||||||
|
Specifying a format or fixed width will slow down the
|
||||||
|
execution a lot (~15-20 times on GNU `seq`):
|
||||||
|
```shell
|
||||||
|
hyperfine -L seq seq,target/release/seq "{seq} -f%g 1000000"
|
||||||
|
hyperfine -L seq seq,target/release/seq "{seq} -w 1000000"
|
||||||
|
```
|
||||||
|
|
||||||
|
Floating point increments, or any negative bound, also degrades the
|
||||||
|
performance (~10-15 times on GNU `seq`):
|
||||||
|
```shell
|
||||||
|
hyperfine -L seq seq,./target/release/seq "{seq} 0 0.000001 1"
|
||||||
|
hyperfine -L seq seq,./target/release/seq "{seq} -100 1 1000000"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Optimizations
|
||||||
|
|
||||||
|
### Buffering stdout
|
||||||
|
|
||||||
|
The original `uutils` implementation of `seq` did unbuffered writes
|
||||||
|
to stdout, causing a large number of system calls (and therefore a large amount
|
||||||
|
of system time). Simply wrapping `stdout` in a `BufWriter` increased performance
|
||||||
|
by about 2 times for a floating point increment test case, leading to similar
|
||||||
|
performance compared with GNU `seq`.
|
||||||
|
|
||||||
[0]: https://github.com/sharkdp/hyperfine
|
[0]: https://github.com/sharkdp/hyperfine
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
// spell-checker:ignore (ToDO) bigdecimal extendedbigdecimal numberparse hexadecimalfloat
|
// spell-checker:ignore (ToDO) bigdecimal extendedbigdecimal numberparse hexadecimalfloat
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io::{stdout, ErrorKind, Write};
|
use std::io::{stdout, BufWriter, ErrorKind, Write};
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, Command};
|
use clap::{Arg, ArgAction, Command};
|
||||||
use num_traits::{ToPrimitive, Zero};
|
use num_traits::{ToPrimitive, Zero};
|
||||||
|
@ -262,8 +262,8 @@ fn print_seq(
|
||||||
padding: usize,
|
padding: usize,
|
||||||
format: Option<&Format<num_format::Float>>,
|
format: Option<&Format<num_format::Float>>,
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
let stdout = stdout();
|
let stdout = stdout().lock();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = BufWriter::new(stdout);
|
||||||
let (first, increment, last) = range;
|
let (first, increment, last) = range;
|
||||||
let mut value = first;
|
let mut value = first;
|
||||||
let padding = if pad {
|
let padding = if pad {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue