Skip to content

Commit 3d1fd05

Browse files
committed
cat: Improve performance of formatting.
Issue #7518 Add a BufWriter over stdout when cat outputs any kind of formattted data. This improves performance considerably.
1 parent 7bd90bb commit 3d1fd05

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

src/uu/cat/src/cat.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
// spell-checker:ignore (ToDO) nonprint nonblank nonprinting ELOOP
77
use std::fs::{metadata, File};
8-
use std::io::{self, IsTerminal, Read, Write};
8+
use std::io::{self, BufWriter, IsTerminal, Read, Write};
99
/// Unix domain socket support
1010
#[cfg(unix)]
1111
use std::net::Shutdown;
@@ -511,9 +511,12 @@ fn write_lines<R: FdReadable>(
511511
) -> CatResult<()> {
512512
let mut in_buf = [0; 1024 * 31];
513513
let stdout = io::stdout();
514-
let mut writer = stdout.lock();
514+
let stdout = stdout.lock();
515+
// Add a 32K buffer for stdout - this greatly improves performance.
516+
let mut writer = BufWriter::with_capacity(32 * 1024, stdout);
515517

516518
while let Ok(n) = handle.reader.read(&mut in_buf) {
519+
eprintln!("Read complete");
517520
if n == 0 {
518521
break;
519522
}
@@ -560,6 +563,14 @@ fn write_lines<R: FdReadable>(
560563
}
561564
pos += offset + 1;
562565
}
566+
// We need to flush the buffer each time around the loop in order to pass GNU tests.
567+
// When we are reading the input from a pipe, the `handle.reader.read` call at the top
568+
// of this loop will block (indefinitely) whist waiting for more data. The expectation
569+
// however is that anything that's ready for output should show up in the meantime,
570+
// and not be buffered internally to the `cat` process.
571+
// Hence it's necessary to flush our buffer before every time we could potentially block
572+
// on a `std::io::Read::read` call.
573+
writer.flush()?;
563574
}
564575

565576
Ok(())

0 commit comments

Comments
 (0)