]> git.lizzy.rs Git - rust.git/commit
Cache and buffer stdout per-task for printing
authorAlex Crichton <alex@alexcrichton.com>
Fri, 25 Oct 2013 00:30:36 +0000 (17:30 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 25 Oct 2013 17:31:57 +0000 (10:31 -0700)
commite8f72c38f4bf74e7291043917fdd0bae1404b407
treea6d0de8c515ae5824ec61b4f21c45e8d7c7e8840
parent3f5b2219cc893b30863f9136703166f306fcc684
Cache and buffer stdout per-task for printing

Almost all languages provide some form of buffering of the stdout stream, and
this commit adds this feature for rust. A handle to stdout is lazily initialized
in the Task structure as a buffered owned Writer trait object. The buffer
behavior depends on where stdout is directed to. Like C, this line-buffers the
stream when the output goes to a terminal (flushes on newlines), and also like C
this uses a fixed-size buffer when output is not directed at a terminal.

We may decide the fixed-size buffering is overkill, but it certainly does reduce
write syscall counts when piping output elsewhere. This is a *huge* benefit to
any code using logging macros or the printing macros. Formatting emits calls to
`write` very frequently, and to have each of them backed by a write syscall was
very expensive.

In a local benchmark of printing 10000 lines of "what" to stdout, I got the
following timings:

  when |  terminal   |  redirected
----------------------------------
before |  0.575s     |   0.525s
after  |  0.197s     |   0.013s
  C    |  0.019s     |   0.004s

I can also confirm that we're buffering the output appropriately in both
situtations. We're still far slower than C, but I believe much of that has to do
with the "homing" that all tasks due, we're still performing an order of
magnitude more write syscalls than C does.
src/libstd/rt/io/buffered.rs
src/libstd/rt/io/stdio.rs
src/libstd/rt/logging.rs
src/libstd/rt/task.rs
src/libstd/rt/uv/uvio.rs
src/libstd/rt/uv/uvll.rs
src/rt/rust_uv.cpp