diff --git a/src/uu/tee/Cargo.toml b/src/uu/tee/Cargo.toml index e52fe7bc022..01485aba94c 100644 --- a/src/uu/tee/Cargo.toml +++ b/src/uu/tee/Cargo.toml @@ -24,6 +24,9 @@ clap = { workspace = true } uucore = { workspace = true, features = ["libc", "parser", "signals"] } fluent = { workspace = true } +[target.'cfg(unix)'.dependencies] +rustix = { workspace = true } + [dev-dependencies] divan = { workspace = true } rustix = { workspace = true, features = ["stdio", "fs"] } diff --git a/src/uu/tee/src/tee.rs b/src/uu/tee/src/tee.rs index f4a5876ee4f..04c7a6e3baa 100644 --- a/src/uu/tee/src/tee.rs +++ b/src/uu/tee/src/tee.rs @@ -197,12 +197,8 @@ impl MultiWriter { fn write_flush(&mut self, buf: &[u8]) -> Result<()> { let mode = self.output_error_mode; - self.writers.retain_mut(|writer| { - let res = (|| { - writer.inner.write_all(buf)?; - writer.inner.flush() - })(); - match res { + self.writers + .retain_mut(|writer| match writer.inner.write_all(buf) { Ok(()) => true, Err(e) => { if let Err(e) = process_error(mode, e, writer, &mut self.ignored_errors) { @@ -210,8 +206,7 @@ impl MultiWriter { } false } - } - }); + }); self.aborted.take().map_or( if self.writers.is_empty() { // This error kind will never be raised by the standard @@ -254,18 +249,34 @@ enum Writer { Stdout(std::io::Stdout), } +// raw syscall avoids buffering which is POSIX requirement +// throughput is better than flush after write_all by unknown reason +// since there is no rustix::io::write_all, we remove buffering by impl from write_all +#[cfg(unix)] impl Write for Writer { fn write(&mut self, buf: &[u8]) -> Result { match self { - Self::File(f) => f.write(buf), - Self::Stdout(s) => s.write(buf), + Self::File(f) => Ok(rustix::io::write(f, buf)?), + Self::Stdout(s) => Ok(rustix::io::write(s, buf)?), } } fn flush(&mut self) -> Result<()> { + Ok(()) + } +} + +#[cfg(not(unix))] +impl Writer { + // override write_all to avoid calling many flush + pub fn write_all(&mut self, buf: &[u8]) -> Result<()> { match self { - Self::File(f) => f.flush(), - Self::Stdout(s) => s.flush(), + // File does not have line buffering + Self::File(f) => f.write_all(buf), + Self::Stdout(s) => { + s.write_all(buf)?; + s.flush() // todo: investigate how to remove flush overhead + } } } }