I read somewhere that snprintf is faster than ostringstream. Has anyone has any experiences with it? If yes why is it faster.
It's quite possible that because sprintf
is part of the CRT that is written in assembly. The ostringstream
is part of the STL, and probably a little more generically written, and has OOP code/overhead to deal with.
std::ostringstream is not designed to be slower, but it generally is slower when implemented. FastFormat's website has some benchmarks.
I've never pinned down why it's slower; my guess is that stream operations basically need to use growable buffers internally and that implies memory allocation which can be slow.
Absolutely this is implementation-specific.
But if you really want to know, write two small programs, and compare them. You would need to include typical usage for what you have in mind, the two programs would need to generate the same string, and you would use a profiler to look at the timing information.
Then you would know.
One reason I know that the printf family of functions are faster than the corresponding C++ functions (cout, cin, and other streams) is that the latter do typechecking. As this usually involves some requests to overloaded operators, it can take some time.
In fact, in programming competitions it is often recommended that you use printf et al rather than cout/cin for precisely this reason.
Some guys would possibly tell you about that the functions can't be faster than each other, but their implementation can. That's right i think i would agree.
You are unlikely to ever notice a difference in other than benchmarks. The reason that c++ streams generally tend to be slower is that they are much more flexible. Flexibility most often comes at the cost of either time or code growth.
In this case, C++ streams are based on stream-buffers. In itself, streams are just the hull that keep formatting and error flags in place, and call the right i/o
facets of the c++ standard library (for example, num_put to print numbers), that print the values, well formatted, into the underlying stream-buffer connected to the c++ stream.
All this mechanisms - the facets, and the buffers, are implemented by virtual functions. While there is indeed no mark note, those functions must be implemented to be slower than c stdio pendants that fact will make them somewhat slower than using c stdio functions normally (i benchmark'ed that some time ago with gcc/libstdc++ and in fact noticed a slowdown - but which you hardly notice in day-by-day usage).
One issue would probably be that the type safety added by ostringstream
carries extra overhead. I've not done any measurements, though.
We replaced some stringstreams in inner loops with sprintf (using statically allocated buffers), and this made a big difference, both in msvc and gcc. I imagine that the dynamic memory management of this code:
{ char buf[100]; int i = 100; sprintf(buf, "%d", i); // do something with buf }
is much simpler than
{ std::stringstream ss; int i = 100; ss << i; std::string s = ss.str(); // do something with s }
but i am very happy with the overall performance of stringstreams.
Using the printf family of functions explicitly forces you to manage the type coercion instead of relying on the type system to do that for you.
As litb said, standard streams support many things we don't always need. Some streams implementation get rid of this never used flexibility, see FAStream for instance.
Yes, if you run the function below on a few million numbers with Visual C++ 5.0, the first version takes about twice as long as the second and produces the same output.
Compiling tight loops into a .exe and running the Windows timethis something.exe' or the Linux
time something' is how I investigate most of my performance curiosities. (`timethis' is available on the web somewhere)
void Hex32Bit(unsigned int n, string &result)
{
#if 0
stringstream ss;
ss
<< hex
<< setfill('0')
<< "0x" << setw(8) << n
;
result = ss.str();
#else
const size_t len = 11;
char temp[len];
_snprintf(temp, len, "0x%08x", n);
temp[len - 1] = '\0';
result = temp;
#endif
}