C vs C++ code optimization for simple array creation and i/o - Stack Overflow
I've been trying to convince a friend of mine to avoid using dynamically allocated arrays and start moving over to the STL vectors. I sent him some sample code to show a couple things that could be done with STL and functors/generators:
#define EVENTS 10000000
struct random_double {
double operator() () { return (double)rand()/RAND_MAX; }
std::vector&lt;double&gt; vd (EVENTS);
generate(vd.begin(), vd.end(), random_double());
copy(vd.begin(), vd.end(), std::ostream_iterator&lt;double&gt;(std::cout, "\n"));
His reply to this, although he feels it's more elegant, is that his own code is faster (by almost a factor of 2!) Here's the C code he replied with:
__inline double random_double() {
return (double)rand()/RAND_MAX;
vd = (double *) malloc(EVENTS*sizeof(double));
for(i=0;i&lt;EVENTS;i++){ vd[i]=random_double(); }
for(i=0;i&lt;EVENTS;i++){ printf("%lf\n",vd[i]); }
free(vd);
So I ran the simple timing test to see just what happens, and here's what I got:
&gt; time ./c++test &gt; /dev/null
real    0m14.665s
user    0m14.577s
&gt; time ./ctest &gt; /dev/null
real    0m8.070s
user    0m8.001s
The compiler options, using g++ were: g++ -finline -funroll-loops. Nothing too special. Can anyone tell me why the C++/STL version is slower in this case? Where is the bottleneck, and will I ever be able to sell my friend on using STL containers?
c++ optimization compiler io share|improve this question edited Dec 18 '09 at 19:32
asked Dec 18 '09 at 19:01
Well, the C code has a glaring memory leak in there for starters...
5 Did you use -O2?
2 C++ benefits much more from -O2 than C does.
@Timo: true, though in this case the process immediately ends and returns the memory back to the OS.
1 Fixed the memory leak - I noted it to my friend as one of the benefits of using the STL - fewer memory leaks :)
Dec 18 '09 at 19:31
for (std::vector&lt;double&gt;::iterator i = vd.begin(); i != vd.end(); ++i)
printf("%lf\n", *i);
koper@elisha ~/b $ time ./cpp &gt; /dev/null
real    0m4.985s
user    0m4.930s
koper@elisha ~/b $ time ./c &gt; /dev/null
real    0m4.973s
user    0m4.920s
Flags used: -O2 -funroll-loops -finline
share|improve this answer answered Dec 18 '09 at 19:15
2 +1 for doing an actual test!
Dec 18 '09 at 19:18
same result as mine :)
Dec 18 '09 at 19:40
Won't this code be spending nearly all its time formatting the floating point number? Even if the ++i gets poorly optimized, it's going to use a small percentage of the cycles.
Dec 18 '09 at 19:54
... If you're trying to compare speed of iteration, get rid of the print. It's the whale in the bathtub.
Dec 18 '09 at 20:12
Almost certainly the use of the iostream library versus printf(). If you want to time the algorithm, you should do your output outside the loop.
1 This. If you have to do output there, make it a fair contest and use printf().
Using STL, especially when using vectors and other nice utility classes, is probably always going to be slower than hand-rolled C code using malloc and inlined functions. There is no real way around it.
That being said, performance is not everything - not nearly so. Using STL provides many other benefits, including:
Better maintainability: It's more expressive, so you get more done in less code, in a more elegant, clean fashion.
Safety: Using vectors is much, much safer than dealing with pointers and malloc directly.
Flexibility: By using vectors with functors, you'd have a much easier time if you needed to grow this collection on the fly, for example.
Productivity: By making the code cleaner, STL promotes reuse much more effectively than lots of individual C routines to do similar functions.
You're really trying to argue about working at a higher level of abstraction - there are tradeoffs here, typically in terms of performance, but there is a reason nearly all development has gone to higher abstraction levels; the gains are far more valuable than the sacrifices in most cases.
Actually the STL vector class was designed so that it would cause (almost) zero overhead when compared to pointers. For the iostreams, you may be right, though.
Dec 18 '09 at 19:57
Yes - but almost 0 != 0. There are some differences in there. For iostreams, it's a much bigger difference.
As I see it, there are three ways to use the vector. 1) Let it grow naturally: overhead of reallocation. 2) Resize to needed size: overhead of zero-initializing all items. 3) Reserve needed size: overhead of still having to check during push_back if there's enough room. That said, it is so much more convenient than keeping track of things yourself, and the performance is mostly good enough.
Dec 19 '09 at 0:34
Yeah - I would always vote to use it, but it does carry a (albeit minor) performance difference from doing things yourself.
Dec 19 '09 at 0:44
I would like to know where people disagree strongly enough for the downvotes, though...
Believing in the bad performance of the insertion iterator of std::cout, I tried to insert the following functor:
void operator()( double d ) { printf("lf\n", d); }
And use for_each on the stl container.
//copy(vd.begin(), vd.end(), std::ostream_iterator&lt;double&gt;(std::cout, "\n"));
std::for_each(vd.begin(), vd.end(), Print() );
As a matter of fact, I now got time.exe raw_vs_stl.exe stl &gt; t.txt
real    0m 2.48s
user    0m 1.68s
for the STL version... while the 'raw' version results in more or less the same.
time.exe raw_vs_stl.exe raw &gt; t.txt
real    0m 9.22s
user    0m 7.89s
sys     0m
Conclusion: vector performance is as good as a raw array's. It's safer and easier to use.
(disclaimer: used VC2005)
share|improve this answer answered Dec 18 '09 at 19:40
One trick for getting an idea of both the difference in speed between two implementations - and the reasons for it - is to delve into the assembly. Assembly really isn't that scary, and shows you exactly what's going on. It's also really handy for seeing what the compiler optimizes out. Generally speaking, more assembly instructions = longer, but keep in mind that some instructions take much longer than others. In Visual Studio (and, I suspect, many other IDs) there's an option to look over assembly interleaved with the corresponding C++ lines. (In VC, this is Debug->Windows->Dissassembly).
share|improve this answer answered Dec 19 '09 at 4:38
I would argue that you are not even running the same code.
The C code has no error checking and leaks memory on an exception.
To be a fare comparison you need to make the C program do what the C++ program is doing.
bool errorNumber = 0;   // Need a way to pass error information back from the function
vd[i]=random_double();
// In C++ this logic is implicit with the use of excptions.
// Any example where you don't do error checking is not valid.
// In real life any code has to have this logic built in by the developer
if (errorNumber != 0)
free(vd);  The cost of freeing the memory is not zero that needs to be factored in.
share|improve this answer edited Jan 29 at 10:52
I disagree. The only functions that can fail in the C example are malloc and printf. malloc may file if he is out of memory, but in that very rare case there is nothing you can do anyway.. printf can in theory file but in practice never does. Anyway, adding that error check is irrelevant to the performance (it will execute so fast that it won't make a difference). Least but not last the memory will be reclaimed by the OS on exit so free() is not necessary (and it's C++'s "fault" that it frees anyway!). But, again, it's only one single free() in a 5 seconds execution time: it won't matter.
I tried to add the error checking and run time ./c > /dev/null again, it actually ran faster (obviously not because of the extra code but because of the non deterministic nature of interrupts).
Dec 18 '09 at 19:37
1 @Koper: Are you really arguing there's no need to call free()? Even if it is freed by the OS at process exit, it is extraordinarily bad coding practice to rely on that. A long running programming could conceivably use more and more memory because of the leak resulting from not calling free. Furthermore, not all OSes will reclaim the memory at process exit, particularly those without a virtual memory manager. Real-time embedded OSes often do not have a VM, so you'd be hosed on such platforms if you didn't properly manage your memory.
Dec 18 '09 at 19:51
@Koper: If you look specifically at this function 'random_double'. Then fine it can never fail. But if you look at this as a general function that has some arbitrory code then you need some way of checking error conditions and forcing the loop to exit and doing the general memory management.
Dec 18 '09 at 20:26
1 @Kopir: If you look at this code as the whole program fine (Ten line program in C/C++ sure. maintance is zero, but in that case who cares about 6 seconds?) I was looking at this as a slice of a real application that was extracted just to do timeing; In this context then yes you do need to do the free, all the other checking, loop termination, error propogation, memory release etc. All the stuff needed by a real application that needs to be explicitly added into a real C application otherwise you are not doing an accurate comparison of the two pieces of code.
There might be occasions were STL is slower, but handrolling maps/sets for multiple insert/remove/lookup would be hard to accomplish.
As Neil pointed out, in speed, printf wins from iostream (also a point in Scott Meyers "More Effective C++, point 23"). However, in more complicated systems. it pays off to be able to write out complete classes inside loggings. The printf way would be to sprintf class information in a function and pass that to the logger as a string parameter. That way, the gain would be smaller.
share|improve this answer answered Dec 18 '09 at 19:22
In high performance situations (such as games), it would be wise to avoid STL containers. Yes they provide excellent functionality, but they also provide a bit of overhead. And that can be disastrous. Personally, I only use std's file handling and the occasional vector.
EDIT: Have your friend take a look at Thrust, which attempts to provide STL like functionality for calculating on the GPU.
share|improve this answer edited Dec 18 '09 at 19:19
answered Dec 18 '09 at 19:05
7191928
That's wrong, as you can see from my answer the performance loss is 0.1%..
Though your answer to the question seems wrong to me, the Thrust link is certainly worth a look!
@Koper: Because of the printf formatting a floating point number, you're not even comparing the performance of the loop. You can't answer this question when you load it down with superfluous unrelated computation.
Not the answer you're looking for?	Browse other questions tagged c++ optimization compiler io or ask your own question.	asked
How to detect I/O in python source code(standard library way of I/O)
C vs C++ code optimization for simple array creation and i/o - Stack Overflow
I've been trying to convince a friend of mine to avoid using dynamically allocated arrays and start moving over to the STL vectors. I sent him some sample code to show a couple things that could be done with STL and functors/generators:
#define EVENTS 10000000
struct random_double {
double operator() () { return (double)rand()/RAND_MAX; }
std::vector&lt;double&gt; vd (EVENTS);
generate(vd.begin(), vd.end(), random_double());
copy(vd.begin(), vd.end(), std::ostream_iterator&lt;double&gt;(std::cout, "\n"));
His reply to this, although he feels it's more elegant, is that his own code is faster (by almost a factor of 2!) Here's the C code he replied with:
__inline double random_double() {
return (double)rand()/RAND_MAX;
vd = (double *) malloc(EVENTS*sizeof(double));
for(i=0;i&lt;EVENTS;i++){ vd[i]=random_double(); }
for(i=0;i&lt;EVENTS;i++){ printf("%lf\n",vd[i]); }
free(vd);
So I ran the simple timing test to see just what happens, and here's what I got:
&gt; time ./c++test &gt; /dev/null
real    0m14.665s
user    0m14.577s
&gt; time ./ctest &gt; /dev/null
real    0m8.070s
user    0m8.001s
The compiler options, using g++ were: g++ -finline -funroll-loops. Nothing too special. Can anyone tell me why the C++/STL version is slower in this case? Where is the bottleneck, and will I ever be able to sell my friend on using STL containers?
c++ optimization compiler io share|improve this question edited Dec 18 '09 at 19:32
asked Dec 18 '09 at 19:01
Well, the C code has a glaring memory leak in there for starters...
5 Did you use -O2?
2 C++ benefits much more from -O2 than C does.
@Timo: true, though in this case the process immediately ends and returns the memory back to the OS.
1 Fixed the memory leak - I noted it to my friend as one of the benefits of using the STL - fewer memory leaks :)
Dec 18 '09 at 19:31
for (std::vector&lt;double&gt;::iterator i = vd.begin(); i != vd.end(); ++i)
printf("%lf\n", *i);
koper@elisha ~/b $ time ./cpp &gt; /dev/null
real    0m4.985s
user    0m4.930s
koper@elisha ~/b $ time ./c &gt; /dev/null
real    0m4.973s
user    0m4.920s
Flags used: -O2 -funroll-loops -finline
share|improve this answer answered Dec 18 '09 at 19:15
2 +1 for doing an actual test!
Dec 18 '09 at 19:18
same result as mine :)
Dec 18 '09 at 19:40
Won't this code be spending nearly all its time formatting the floating point number? Even if the ++i gets poorly optimized, it's going to use a small percentage of the cycles.
Dec 18 '09 at 19:54
... If you're trying to compare speed of iteration, get rid of the print. It's the whale in the bathtub.
Dec 18 '09 at 20:12
Almost certainly the use of the iostream library versus printf(). If you want to time the algorithm, you should do your output outside the loop.
1 This. If you have to do output there, make it a fair contest and use printf().
Using STL, especially when using vectors and other nice utility classes, is probably always going to be slower than hand-rolled C code using malloc and inlined functions. There is no real way around it.
That being said, performance is not everything - not nearly so. Using STL provides many other benefits, including:
Better maintainability: It's more expressive, so you get more done in less code, in a more elegant, clean fashion.
Safety: Using vectors is much, much safer than dealing with pointers and malloc directly.
Flexibility: By using vectors with functors, you'd have a much easier time if you needed to grow this collection on the fly, for example.
Productivity: By making the code cleaner, STL promotes reuse much more effectively than lots of individual C routines to do similar functions.
You're really trying to argue about working at a higher level of abstraction - there are tradeoffs here, typically in terms of performance, but there is a reason nearly all development has gone to higher abstraction levels; the gains are far more valuable than the sacrifices in most cases.
Actually the STL vector class was designed so that it would cause (almost) zero overhead when compared to pointers. For the iostreams, you may be right, though.
Dec 18 '09 at 19:57
Yes - but almost 0 != 0. There are some differences in there. For iostreams, it's a much bigger difference.
As I see it, there are three ways to use the vector. 1) Let it grow naturally: overhead of reallocation. 2) Resize to needed size: overhead of zero-initializing all items. 3) Reserve needed size: overhead of still having to check during push_back if there's enough room. That said, it is so much more convenient than keeping track of things yourself, and the performance is mostly good enough.
Dec 19 '09 at 0:34
Yeah - I would always vote to use it, but it does carry a (albeit minor) performance difference from doing things yourself.
Dec 19 '09 at 0:44
I would like to know where people disagree strongly enough for the downvotes, though...
Believing in the bad performance of the insertion iterator of std::cout, I tried to insert the following functor:
void operator()( double d ) { printf("lf\n", d); }
And use for_each on the stl container.
//copy(vd.begin(), vd.end(), std::ostream_iterator&lt;double&gt;(std::cout, "\n"));
std::for_each(vd.begin(), vd.end(), Print() );
As a matter of fact, I now got time.exe raw_vs_stl.exe stl &gt; t.txt
real    0m 2.48s
user    0m 1.68s
for the STL version... while the 'raw' version results in more or less the same.
time.exe raw
_vs_stl.exe raw &gt; t.txt
real    0m 9.22s
user    0m 7.89s
sys     0m
Conclusion: vector performance is as good as a raw array's. It's safer and easier to use.
(disclaimer: used VC2005)
share|improve this answer answered Dec 18 '09 at 19:40
One trick for getting an idea of both the difference in speed between two implementations - and the reasons for it - is to delve into the assembly. Assembly really isn't that scary, and shows you exactly what's going on. It's also really handy for seeing what the compiler optimizes out. Generally speaking, more assembly instructions = longer, but keep in mind that some instructions take much longer than others. In Visual Studio (and, I suspect, many other IDs) there's an option to look over assembly interleaved with the corresponding C++ lines. (In VC, this is Debug->Windows->Dissassembly).
share|improve this answer answered Dec 19 '09 at 4:38
I would argue that you are not even running the same code.
The C code has no error checking and leaks memory on an exception.
To be a fare comparison you need to make the C program do what the C++ program is doing.
bool errorNumber = 0;   // Need a way to pass error information back from the function
vd[i]=random_double();
// In C++ this logic is implicit with the use of excptions.
// Any example where you don't do error checking is not valid.
// In real life any code has to have this logic built in by the developer
if (errorNumber != 0)
free(vd);  The cost of freeing the memory is not zero that needs to be factored in.
share|improve this answer edited Jan 29 at 10:52
I disagree. The only functions that can fail in the C example are malloc and printf. malloc may file if he is out of memory, but in that very rare case there is nothing you can do anyway.. printf can in theory file but in practice never does. Anyway, adding that error check is irrelevant to the performance (it will execute so fast that it won't make a difference). Least but not last the memory will be reclaimed by the OS on exit so free() is not necessary (and it's C++'s "fault" that it frees anyway!). But, again, it's only one single free() in a 5 seconds execution time: it won't matter.
I tried to add the error checking and run time ./c > /dev/null again, it actually ran faster (obviously not because of the extra code but because of the non deterministic nature of interrupts).
Dec 18 '09 at 19:37
1 @Koper: Are you really arguing there's no need to call free()? Even if it is freed by the OS at process exit, it is extraordinarily bad coding practice to rely on that. A long running programming could conceivably use more and more memory because of the leak resulting from not calling free. Furthermore, not all OSes will reclaim the memory at process exit, particularly those without a virtual memory manager. Real-time embedded OSes often do not have a VM, so you'd be hosed on such platforms if you didn't properly manage your memory.
Dec 18 '09 at 19:51
@Koper: If you look specifically at this function 'random_double'. Then fine it can never fail. But if you look at this as a general function that has some arbitrory code then you need some way of checking error conditions and forcing the loop to exit and doing the general memory management.
Dec 18 '09 at 20:26
1 @Kopir: If you look at this code as the whole program fine (Ten line program in C/C++ sure. maintance is zero, but in that case who cares about 6 seconds?) I was looking at this as a slice of a real application that was extracted just to do timeing; In this context then yes you do need to do the free, all the other checking, loop termination, error propogation, memory release etc. All the stuff needed by a real application that needs to be explicitly added into a real C application otherwise you are not doing an accurate comparison of the two pieces of code.
There might be occasions were STL is slower, but handrolling maps/sets for multiple insert/remove/lookup would be hard to accomplish.
As Neil pointed out, in speed, printf wins from iostream (also a point in Scott Meyers "More Effective C++, point 23"). However, in more complicated systems. it pays off to be able to write out complete classes inside loggings. The printf way would be to sprintf class information in a function and pass that to the logger as a string parameter. That way, the gain would be smaller.
share|improve this answer answered Dec 18 '09 at 19:22
In high performance situations (such as games), it would be wise to avoid STL containers. Yes they provide excellent functionality, but they also provide a bit of overhead. And that can be disastrous. Personally, I only use std's file handling and the occasional vector.
EDIT: Have your friend take a look at Thrust, which attempts to provide STL like functionality for calculating on the GPU.
share|improve this answer edited Dec 18 '09 at 19:19
answered Dec 18 '09 at 19:05
7191928
That's wrong, as you can see from my answer the performance loss is 0.1%..
Though your answer to the question seems wrong to me, the Thrust link is certainly worth a look!
@Koper: Because of the printf formatting a floating point number, you're not even comparing the performance of the loop. You can't answer this question when you load it down with superfluous unrelated computation.
Not the answer you're looking for?	Browse other questions tagged c++ optimization compiler io or ask your own question.	asked
How to detect I/O in python source code(standard library way of I/O)