STL speed question

Started by
45 comments, last by phillip_fletcher 20 years, 11 months ago
Given:
  
class CGraphicalObject
{
public:
     virtual bool Draw(void) { /* draw stuff */ return true; }
};

  
Which is faster?
  
typedef std::list<CGraphicalObject*> ObjectPtrList;

ObjectPtrList ListOfObjects;

// list is filled elsewhere....


ObjectPtrList::iterator ObjectIter;
for(ObjectIter = ListOfObjects.begin(); ObjectIter != ListOfObjects.end(); ObjectIter++)
{
     (*ObjectIter)->Draw();
}
  
Or
  
typedef std::list<CGraphicalObject*> ObjectPtrList;

ObjectPtrList ListOfObjects;

// list is filled elsewhere....

std::for_each(ListOfObjects.begin(), ListOfObjects.end(), std::mem_fun(CGraphicalObject::Draw));
  
Advertisement
I would venture to say that in this instance, the second would be slightly faster as it caches the call to end().

But not by much...
daerid@gmail.com
Don''t worry about it. Period. Do whatever you think is a more concise and readable form.

A lot of beginning and even intermediate programmers make the mistake of premature optimization, trying to wring every last cycle out of their CPU before they even have any idea where the bottleneck is.

Three rules of optimization, stolen from someone or other here (feel free to speak up and take credit):
1. Don''t optimize.
2. (for advanced programmers) Don''t optimize yet.
3. Use a profiler.

How appropriate. You fight like a cow.
Premature Optimization is the #1 cause of non-written code. It is also the source of all evil. Satan was spawned because God tried to prematurely optimize his code.

Stay away from it. The bottom line is, ugly code that works is ALWAYS better than elegant / optimized code that DOESN''T work.

So just make it work and then worry about it after it works.
daerid@gmail.com
Hmm, I have to partially take exception with what daerid said.

Ugly code that works is bad. elegant, unoptimized code that also works is good. Ugly, optimized code that really, really works is probably bad.

How appropriate. You fight like a cow.
Well this is actually out of code that I wrote a few years ago. I'm going over a few of the drawing routines, which are the bottleneck, the former was the original form of the code. And after looking at it recently, optimization is certainly not premature, its unavoidable (And for the "Don't worry about it", its my job to worry about it, I have the task of making the application run fast, lucky me huh ). I like the way that the "for_each" works, and I personally think it is cleaner, but either version is readable to my co-workers, and I. I wasn't sure if the STL implementations were inline, or not, in which case all, I would imagine that all the function calls would add alot of overhead. I'm not sure. I do know that the STL implementation(with VC) of "for_each" contains alot of function calls, probably more than the for loop.

Thank you all for you words though, I'll just assume that the too are fairly equal in speed.


[edited by - phillip_fletcher on May 5, 2003 3:17:37 PM]
[RANT]

quote:
[...] Premature Optimization [...]

I regularily get neurological seizures, when I see/read/hear this term. This whole concept of "premature optimization", which seems to be so loved by the academic crowd, is one of the most idiotic concepts I know of. Just after hungarian notation. Welcome to the the world of "modern" software development: extremely slow and bloated code, that takes ten times more space than it should, and executes ten times slower than it could. Great. And often this is not the result of inherently bad design, but the result of simple little errors from the "premature optimization" brainwashing.

quote:
Three rules of optimization, stolen from someone or other here (feel free to speak up and take credit):
1. Don''t optimize.
2. (for advanced programmers) Don''t optimize yet.
3. Use a profiler.

I fully agree with 3, no question about that. I do not entirely agree with 2. There comes a point in your programming experience, where you instinctively know, that a certain piece of code is going to be a bottleneck. For example, let''s take a string or a vector class. You know that it is going to be used throughout your code. Emphasis is on the amount of potential use: if some piece of (library) code is going to be extensively used, then chances are, that it will sooner or later end up in time critical parts. It can not be wrong to optimize such code beforehand. In fact, it will even increase your productivity. And I certainly do not agree with point 1. Actually, I think that point 1 is one of the main reasons for low-quality, slow and bloated code.

And just to clear up another common mistake: optimized code does not need to be ugly, or unmaintainable. Optimized code doesn''t necessarilly mean ASM either. Optimized code is a way of thinking and organizing your algorithmic structures. Optimizing is also programming with speed and efficiency in mind. Optimized programming is not using a std::map, if an std::vector would do it. Or not using operator new() in a string class for small elements, but a pool allocator. It''s choosing the right tools (ie. structures and algorithms) to do the job. Unfortunately, lots of people lose sight of that: they write bloated and slow code, with the idea of subsequent optimization in the head. "We''ll optimize it later, first it needs to run". Bullshit. We all know, that it is never going to be optimized later - if the product works, it is considered ready for shipping. Try to convince the marketing departement, that the apparently fully opeartional (but slow) software needs another two month optimization pass. Good luck.

[/RANT]
Finally, someone who can relate
quote:Original post by Yann L
I regularily get neurological seizures, when I see/read/hear this term. This whole concept of "premature optimization", which seems to be so loved by the academic crowd, is one of the most idiotic concepts I know of. Just after hungarian notation. Welcome to the the world of "modern" software development: extremely slow and bloated code, that takes ten times more space than it should, and executes ten times slower than it could. Great. And often this is not the result of inherently bad design, but the result of simple little errors from the "premature optimization" brainwashing.

Well, of course, it''s not an either-or situation. You make a good point about optimized design in terms of program flow, data structures, etc... what I''d call "macro-optimization". My comments, and stating of those rules, were more geared towards micro-optimization, which this seems to gear more towards. In this case, since he''s using the member function pointer functor in foreach, there''ll be an extra function dereference and no chance to inline. Since it''s a virtual function, though, you wouldn''t be inlining much anyway if you wrote a custom functor--just the vtable dereference. In the for loop case, he isn''t caching end(), but it''s not as weighty as a branch (on x86) so not much to worry about there.

But all of this is meaningless... it''s a few clock cycles per object. Meanwhile, each object is undoubtedly taking at least thousands of clock cycles each in the Draw() call. So I look at this, and my brain yells at me, "it''s an outer loop--the bottleneck isn''t here." I definitely agree that macro-optimizations should be implemented from day 1, starting with design.

You make a good point about optimizing commonly used helper functions. But I believe that this is a fairly rare case to be encountered on these boards--I''ve noticed that the majority of people asking about optimizations are not hacking a matrix transform or an FFT, but rather asking about a code structure like this. I think that this is partially because most commonly used functions have already been written for people, either in D3DX (though don''t get me started on the optimization of a few of those functions) or the CRT.

How appropriate. You fight like a cow.
quote:
In this case, since he''s using the member function pointer functor in foreach, there''ll be an extra function dereference and no chance to inline. Since it''s a virtual function, though, you wouldn''t be inlining much anyway if you wrote a custom functor--just the vtable dereference. In the for loop case, he isn''t caching end(), but it''s not as weighty as a branch (on x86) so not much to worry about there.

True, but I wasn''t specifically referring to his case. It was more a general purpose rant

I fully agree with you about the macro and micro-optimization issue. But unfortunately, this premature optimization paradigm seems to spread out recently, widely out of control. It goes so far, that efficient code is losing all importance, ie. "the compiler is psychic and will do everything for me" behaviour. OK, modern compilers can do much more today, but the overall structure still comes from a human mind.

And what is even more alarming, is that this stance seems to be more and more common with programming students in the CS domain, even majored ones still have this idea.

This topic is closed to new replies.

Advertisement