4 ms·
Lots of people are writing Rust code who aren't previously versed in the nuances of optimizing bare-metal code. They're (reasonably) expecting amazing performan
by brundolf 5y ago
Lots of people are writing Rust code who aren't previously versed in the nuances of optimizing bare-metal code. They're (reasonably) expecting amazing performance, because Rust tends to give you that by default compared with higher-level languages. But repeated calls to println!() is one of the biggest and easiest-to-make performance mistakes for those newcomers, so I think it's fair to call it out.
With that said, the OP could definitely have done a better job making it clear that this problem isn't specific to Rust
- not2b 5y agoDevelopers from other languages, like C, C++, or even Python, would not have expected this particular problem, because it wouldn't have occurred to them that the thing they get from doing a file-open call and that the JSON reader library accepts is a raw file descriptor (for C programmers, the result of 'open' rather than 'fopen') that does unbuffered I/O. In other languages libraries are oriented around buffered I/O structures (a FILE or an iostream).
- BoorishBears 5y agoTo me the biggest reason for the surprise is the signature for 'write' I'm used to a raw stream allowing a few specific operations: - read/write/peek one byte - write a byte array, but you must explicitly specify length and offset So seeing a call that simply takes an entire byte string and writes it gives me "buffered I/O vibes". It's hard to quantify, but with how ubiquitous that pattern is I'd be surprised if there are a lot of people who expect similar.
- not2b 5y agoThis had been upvoted and now it is downvoted, even though it is obviously true, as the article demonstrates.
- oconnor663 5y agoFor what it's worth, I run into the same nuances frequently in Python. For example I often want to run some_script.py | tee log.txt But by default, Python will turn off line buffering when it detects it's not talking to a tty. So unless you know to call flush, or to add the right env var or interpreter flag, you're not going to see any early output from tee. This can be super confusing for newer programmers.
- DarylZero 5y agoIt's not Python, it's a generic Unix problem. This is why stdbuf exists. http://www.pixelbeat.org/programming/stdio_buffering/ http://www.pixelbeat.org/programming/stdio_buffering/
- css 5y ago> Python will turn off line buffering when it detects it's not talking to a tty Okay, I’ve been running into a bug in one of my Rust programs and I think this comment has the answer. My program uses a Command [0] to listen to stdin and stdout. Theoretically that Command should terminate when the parent process dies, but if the Command is a Python script that doesn’t include a `print()` with `flush=True`, it doesn’t die. I think you might have found my problem for me. [0]: https://docs.rs/tokio/1.15.0/tokio/process/struct.Command.html https://docs.rs/tokio/1.15.0/tokio/process/struct.Command.ht...
- deleted 5y ago[deleted]
- duped 5y agoI don't think it's fair to call out since no one is putting a println! in hot loops unless they're debugging
- brundolf 5y agoNot remotely true. I learned this lesson the hard way a couple years ago while working on a program that did exactly that.
- otterley 5y agoIt sounds to me like println! and other I/O macros and functions should buffer I/O by default if the file descriptor is not a terminal. This would be consistent with how other languages’ standard libraries behave.