C++ IOStreams Considered Harmful
Henrique Bucher
Financial Engineer | Substack Bestseller Author | C++/FPGA/Quant/Trading/HFT/ULL | PhD/MSc/BSc Engineering
This should not be any news at this point for anyone that has used C++ in a performance-oriented environment: never use iostreams in production code. Ever.
However I was not aware of how bad things were in C++land since we were all focused on trying to keep up with the deluge of functional programming coming from the standard side (variadics anyone?).
On a recent post on [Visual Studio Team Blog] it was stated that string/double and string/float conversion has "improved" 19.5 times. Wow! Well, it would be very nice IF the problem was not other than sometime before 2013 someone made the performance 20 times worse! So, yes, there was a three-year long regression that only now was fixed. We encourage you to fix it asap.
To add insult to injury, the old code was printing the wrong result as well. So, please update asap.
However, who still uses iostream in production code anyway? Answer: a ton of companies, including many trading companies. There are still heated debates on whether to use C++ or the "old-school" glibc functions.
Here is the reality: all C++ libraries are just wrappers around the glibc, which does the bulk of the work.
Repeat: C++ implementations are just a thin shell on top of glibc. If you do not believe, just have a look at say cstdio> code:
Or please head to the "Modern C++" std::chrono and look inside the implementation of std::high_resolution_clock::now().
First, there is no high_resolution_clock, it is aliased to system_clock.
Second, most of the C++ methods are explicitly mapped to the GLIBC C-functions:
And third, now() just makes a dumb call to clock_gettime(). Another compiler path, depending on system, would call gettimeofday(). I removed several of these #ifdefs for clarity.
Now, iostreams goes one step ahead in the worse possible direction. It actually forces all the C++ library implementations to make a virtual function call for every character printed. Yes, you heard it right. One virtual function call for every character printed. More details [here].
If that wasnt enough to convince you, let's have a look at some numbers. You have seen in the graph before that the iostream performance is 3x slower than "CRT" on Windows. I have just run similar tests on gcc/g++ 5.3 and the results confirm: strtod() takes average 450 cycles while the istream equivalent takes 1,200 cycles or almost 3x slower. Boost's lexical_cast is even worse at 1,300 cycles which suggests it is another wrapper on top of something else.
So, if you use iostreams do use do yourself a favor and do not use it for anything that is performance oriented.
Ask what is "Modern C++" replacement and you get this type of answer from a C++/STL maintainer:
Q: So what's the replacement for iostreams in Modern C++?
A: I don't believe there is one. I still recommend cstdio. :)
So folks, please go back to GLIBC and use it. Or use something more sophisticated as EA replacement STL. As they put it:
14 - Why replace standard library functions?
Often you will see game programmers avoid using functions from the C and C++ standard library and instead use re-implemented versions. The reasons for this depend on the individual case but are usually driven by some practical performance issue.
That's very politically correct.
About me: I am a Generation X consultant that started in computing programming Assembly 6502 in the first Apple ][. We offer services in many fields including high-performance computing (HPC), numerical methods, machine learning, big data/tick warehouses. We also provide HB Quant, a suite of high-performance libraries for statistical arbitrage and high-frequency trading.
Link: https://www.vitorian.com/x1/areas-of-expertise
UPDATE 1: I have built some tests in response to Jason Tuner's video. You can find them here.
Ph.D. Computer Science
7 年These are very interesting points. I think many aspect of C++ and modern C++ were designed and implemented with the sole goal of adding features to C++, at the cost of performance and/or clarity of code.
Sciences and Technology enthusiast | Blockchain Core Developer (C++) | High Performance Computing | Python
7 年It there is performance bottleneck in modern C++, so why committe spend so much to make it exists? Why they don't refine C++98 then let user choose library for feature like string, threading, io, etc?
Building teams, building high reliability systems
8 年Even in code that is not performance critical, iostreams are often more awkward to use and need more LOC than *printf* for equivalent functionality.