Hacker News new | ask | show | jobs
by Freaky 1085 days ago
C and Python have adaptive buffering for stdout: if the output is a terminal they flush on newlines, otherwise they only flush when their internal buffer is full.

Here's a C program counting, with a 1ms delay between lines. The second column is a duration since the previous read():

   $ ./out | rtss
   4.7ms    4.7ms | 1
   4.7ms          | 2
   4.7ms          | 3
   4.7ms          | 4
   4.8ms    exit status: 0
You can see they were all written in one go. When allocated a terminal, they come out line by line:

   $ rtss --pty ./out
   0.8ms    0.8ms | 1
   1.9ms    1.1ms | 2
   3.0ms    1.1ms | 3
   4.1ms    1.1ms | 4
   4.3ms    exit status: 0
Rust lacks this adaptive behaviour for output, and will always produce the second result, terminal or not.

Technically it unconditionally wraps stdout in a LineWriter (https://doc.rust-lang.org/std/io/struct.LineWriter.html), which always flushes if it sees a write containing a newline. To maximise throughput you therefore want to batch writes of multiple lines together, for example by wrapping it in a BufWriter.