mirror of
https://github.com/sharkdp/fd
synced 2024-11-05 16:58:21 +00:00
walk: Flush stdout in batches
The previous behaviour was designed to mimic the output buffering of typical UNIX tools: line-buffered if stdout is a TTY, and fully-buffered otherwise. More precicely, when printing to a terminal, fd would flush explicitly after printing any buffered results, then flush after every single result once streaming mode started. When not printing to a terminal, fd never explicitly flushed, so writes would only happen as the BufWriter filled up. The new behaviour actually unifies the TTY and non-TTY cases: we flush after printing the buffered results, then once we start streaming, we flush after each batch, but *only when the channel is empty*. This provides a good balance: if the channel is empty, the receiver thread might as well flush before it goes to sleep waiting for more results. If the channel is non-empty, we might as well process those results before deciding to flush. For TTYs, this should improve performance by consolidating write() calls without sacrificing interactivity. For non-TTYs, we'll be flushing more often, but only when the receiver would otherwise have nothing to do, thus improving interactivity without sacrificing performance. This is particularly handy when fd is piped into another command (such as head or grep): with the old behaviour, fd could wait for the whole traversal to finish before printing anything. With the new behaviour, fd will print those results soon after they are received. Fixes #1313.
This commit is contained in:
parent
fea1622724
commit
16c2d1e1d0
1 changed files with 6 additions and 2 deletions
|
@ -214,7 +214,6 @@ impl<'a, W: Write> ReceiverBuffer<'a, W> {
|
|||
}
|
||||
ReceiverMode::Streaming => {
|
||||
self.print(&dir_entry)?;
|
||||
self.flush()?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,6 +231,11 @@ impl<'a, W: Write> ReceiverBuffer<'a, W> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have another batch ready, flush before waiting
|
||||
if self.mode == ReceiverMode::Streaming && self.rx.is_empty() {
|
||||
self.flush()?;
|
||||
}
|
||||
}
|
||||
Err(RecvTimeoutError::Timeout) => {
|
||||
self.stream()?;
|
||||
|
@ -285,7 +289,7 @@ impl<'a, W: Write> ReceiverBuffer<'a, W> {
|
|||
|
||||
/// Flush stdout if necessary.
|
||||
fn flush(&mut self) -> Result<(), ExitCode> {
|
||||
if self.config.interactive_terminal && self.stdout.flush().is_err() {
|
||||
if self.stdout.flush().is_err() {
|
||||
// Probably a broken pipe. Exit gracefully.
|
||||
return Err(ExitCode::GeneralError);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue