Skip to content

Commit fe4aba2

Browse files
committed
tee: improve throughput by raw syscall
1 parent d928f05 commit fe4aba2

2 files changed

Lines changed: 24 additions & 13 deletions

File tree

src/uu/tee/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ doctest = false
2121

2222
[dependencies]
2323
clap = { workspace = true }
24+
rustix = { workspace = true, features = ["stdio", "fs"] }
2425
uucore = { workspace = true, features = ["libc", "parser", "signals"] }
2526
fluent = { workspace = true }
2627

2728
[dev-dependencies]
2829
divan = { workspace = true }
29-
rustix = { workspace = true, features = ["stdio", "fs"] }
3030
tempfile = { workspace = true }
3131
uucore = { workspace = true, features = ["benchmark"] }
3232

src/uu/tee/src/tee.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,21 +197,16 @@ impl MultiWriter {
197197

198198
fn write_flush(&mut self, buf: &[u8]) -> Result<()> {
199199
let mode = self.output_error_mode;
200-
self.writers.retain_mut(|writer| {
201-
let res = (|| {
202-
writer.inner.write_all(buf)?;
203-
writer.inner.flush()
204-
})();
205-
match res {
200+
self.writers
201+
.retain_mut(|writer| match writer.inner.write_all(buf) {
206202
Ok(()) => true,
207203
Err(e) => {
208204
if let Err(e) = process_error(mode, e, writer, &mut self.ignored_errors) {
209205
self.aborted.get_or_insert(e);
210206
}
211207
false
212208
}
213-
}
214-
});
209+
});
215210
self.aborted.take().map_or(
216211
if self.writers.is_empty() {
217212
// This error kind will never be raised by the standard
@@ -254,18 +249,34 @@ enum Writer {
254249
Stdout(std::io::Stdout),
255250
}
256251

252+
// raw syscall avoids buffering which is POSIX requirement
253+
// throughput is better than flush after write_all by unknown reason
254+
// since there is no rustix::io::write_all, we remove buffering by impl from write_all
255+
#[cfg(any(unix, target_os = "wasi"))]
257256
impl Write for Writer {
258257
fn write(&mut self, buf: &[u8]) -> Result<usize> {
259258
match self {
260-
Self::File(f) => f.write(buf),
261-
Self::Stdout(s) => s.write(buf),
259+
Self::File(f) => Ok(rustix::io::write(f, buf)?),
260+
Self::Stdout(s) => Ok(rustix::io::write(s, buf)?),
262261
}
263262
}
264263

265264
fn flush(&mut self) -> Result<()> {
265+
Ok(())
266+
}
267+
}
268+
269+
#[cfg(not(any(unix, target_os = "wasi")))]
270+
impl Writer {
271+
// override write_all to avoid calling many flush
272+
pub fn write_all(&mut self, buf: &[u8]) -> Result<()> {
266273
match self {
267-
Self::File(f) => f.flush(),
268-
Self::Stdout(s) => s.flush(),
274+
// File does not have line buffering
275+
Self::File(f) => f.write_all(buf),
276+
Self::Stdout(s) => {
277+
s.write_all(buf)?;
278+
s.flush() // todo: investigate how to remove flush overhead
279+
}
269280
}
270281
}
271282
}

0 commit comments

Comments
 (0)