[iterator] huge differences in compile time between iterator_facade and iterator helpers

While in the process of replacing iterator helpers from <boost/operators.hpp> in favor of boost::iterator_facade as my internal iterator generation lib in Boost.MultiIndex, I've discovered an unpleasant increase in compilation times. The attached program shows the problem. Compilation times when using boost::iterator_facade are *way* higher than with good old boost::bidirectional_iterator_helper (to test it yourself, just comment/uncomment the line "#define USE_BOOST_ITERATOR" in the program): MSVC++ 6.0: iterator_facade: ~7 sec. bidirectional_iterator_helper: less than 1 sec. GCC 3.2 iterator_facade: 4.9 sec. bidirectional_iterator_helper: 2.5 sec. My questions: 1. Maybe the test program is flawed and has some (unseen by me) bias in favor of bidirectional_iterator_helper? 2. If not so, why is iterator_facade so very expensive? Is there any way to alleviate the problem? As it stands, I'm not so sure it's a good idea to adopt boost::iterator_facade: my local tests for Boost.MultiIndex show an overall increase in compilation time of around 25% :( Thanks for your help, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Joaquín Mª López Muñoz <joaquin@tid.es> writes:
While in the process of replacing iterator helpers from <boost/operators.hpp> in favor of boost::iterator_facade as my internal iterator generation lib in Boost.MultiIndex, I've discovered an unpleasant increase in compilation times.
The attached program shows the problem. Compilation times when using boost::iterator_facade are *way* higher than with good old boost::bidirectional_iterator_helper (to test it yourself, just comment/uncomment the line "#define USE_BOOST_ITERATOR" in the program):
MSVC++ 6.0: iterator_facade: ~7 sec. bidirectional_iterator_helper: less than 1 sec. GCC 3.2 iterator_facade: 4.9 sec. bidirectional_iterator_helper: 2.5 sec.
I had to modify the test to eliminate undefined behavior and make sure dead code elimination didn't kick in (enclosed). Results: GCC 3.4.4: Test 1 discarded Test 2 with operator library: 1.469 with iterator library: 2.282 Test 3 with operator library: 1.438 with iterator library: 2.297 GCC 4.0.2: Test 1 discarded Test 2 with operator library: 1.468 with iterator library: 1.579 Test 3 with operator library: 1.453 with iterator library: 1.563 MSVC 7.1 Test 1 discarded Test 2 with operator library: 1.219 with iterator library: 1.187 Test 3 with operator library: 1.203 with iterator library: 1.188 Unfortunately I couldn't get vc6 or vc7 to compile it :( Now, here's the interesting thing: If you change the needless postincrement you're using into preincrement, you get: GCC 3.4.4: Test 1 discarded Test 2 with operator library: 1.485 with iterator library: 1.453 Test 3 with operator library: 1.437 with iterator library: 1.453
My questions: 1. Maybe the test program is flawed and has some (unseen by me) bias in favor of bidirectional_iterator_helper?
The postincrement comes to mind.
2. If not so, why is iterator_facade so very expensive? Is there any way to alleviate the problem?
I don't know; you could experiment with defining postincrement in terms of preincrement. You could also look at what type postfix_increment_result is computing in iterator_facade.hpp
As it stands, I'm not so sure it's a good idea to adopt boost::iterator_facade: my local tests for Boost.MultiIndex show an overall increase in compilation time of around 25% :(
If your code is correct with bidirectional_iterator_helper, of course there's no need to switch. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Joaquín Mª López Muñoz <joaquin@tid.es> writes:
I had to modify the test to eliminate undefined behavior and make sure dead code elimination didn't kick in (enclosed). Results:
GCC 3.4.4: Test 1 discarded
Test 2 with operator library: 1.469 with iterator library: 2.282
Test 3 with operator library: 1.438 with iterator library: 2.297
GCC 4.0.2: Test 1 discarded
Test 2 with operator library: 1.468 with iterator library: 1.579
Test 3 with operator library: 1.453 with iterator library: 1.563
MSVC 7.1 Test 1 discarded
Test 2 with operator library: 1.219 with iterator library: 1.187
Test 3 with operator library: 1.203 with iterator library: 1.188
Sorry for being dumb but is this compile time or run time? Thomas -- Thomas Witt witt@acm.org

Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
Joaquín Mª López Muñoz <joaquin@tid.es> writes:
I had to modify the test to eliminate undefined behavior and make sure dead code elimination didn't kick in (enclosed). Results:
Sorry for being dumb but is this compile time or run time?
Runtime. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
Joaquín Mª López Muñoz <joaquin@tid.es> writes:
I had to modify the test to eliminate undefined behavior and make sure dead code elimination didn't kick in (enclosed). Results:
Sorry for being dumb but is this compile time or run time?
Runtime.
AFAICS Joaquín's question is with respect to compiletime. Thomas -- Thomas Witt witt@acm.org

Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
Thomas Witt <witt@acm.org> writes:
David Abrahams wrote:
Joaquín Mª López Muñoz <joaquin@tid.es> writes:
I had to modify the test to eliminate undefined behavior and make sure dead code elimination didn't kick in (enclosed). Results:
Sorry for being dumb but is this compile time or run time?
Runtime.
AFAICS Joaquín's question is with respect to compiletime.
Hmm. Well we also have some abstraction penalty issue with older compilers, it seems. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams <dave@boost-consulting.com> writes:
Now, here's the interesting thing: If you change the needless postincrement you're using into preincrement, you get:
GCC 3.4.4: Test 1 discarded
Test 2 with operator library: 1.485 with iterator library: 1.453
Test 3 with operator library: 1.437 with iterator library: 1.453
When I do the same to your test (slightly modified; see enclosed) I get: MSVC-6.0 using iterator lib: ---- using iterator lib: 8.812 using iterator lib: 8.797 using operator lib: ----- using operator lib: 5.688 using operator lib: 5.703 GCC-3.4.4 using operator lib: ----- using operator lib: 4.844 using operator lib: 4.859 using iterator lib: ---- using iterator lib: 4.86 using iterator lib: 4.875 So it looks like the penalty is elsewhere for vc6 -- Dave Abrahams Boost Consulting www.boost-consulting.com

Ah, whoops, I promised to include this: -- Dave Abrahams Boost Consulting www.boost-consulting.com

Joaquín Mª López Muñoz wrote:
MSVC++ 6.0: iterator_facade: ~7 sec. bidirectional_iterator_helper: less than 1 sec. GCC 3.2 iterator_facade: 4.9 sec. bidirectional_iterator_helper: 2.5 sec.
FWIW my results with gcc4 on darwin are in line with what you see from gcc 3.2
My questions: 1. Maybe the test program is flawed and has some (unseen by me) bias in favor of bidirectional_iterator_helper?
Well it is certainly biased in that it is simple ;-).
2. If not so, why is iterator_facade so very expensive? Is there any way to alleviate the problem?
iterator_facade covers more ground than the iterator helpers. Forinstance it deals with new iterator categories and iterators that don't fit the C++03 categories well. That being said as long as you don't need this functionality ... There is a chance of a future revision of facade improving compile times. But this won't happen any time soon.
As it stands, I'm not so sure it's a good idea to adopt boost::iterator_facade:
To be honest I don't know either. As long as you don't need the extended functionality of iterator_facade you might be better of staying with the helpers for now. HTH Thomas -- Thomas Witt witt@acm.org
participants (3)
-
David Abrahams
-
Joaquín Mª López Muñoz
-
Thomas Witt