When executing the following snippet: #include <list> int main() { std::list<int> l; } the function __common_pool_policy<__pool,true>::_S_get_pool() is called three times! Yet the result of the call is discarded each time. As a matter of fact, no memory has even been allocated by the program, so the pool is useless. These three calls are due to the __mt_alloc class. Excerpt from ext/mt_alloc.h:655: __mt_alloc() throw() { __policy_type::_S_get_pool(); } __mt_alloc(const __mt_alloc&) throw() { __policy_type::_S_get_pool(); } I didn't see anything in the online documentation ext/mt_allocator.html that states that _S_get_pool must be called three times before _S_initialize_once can even be called (this function is called by allocate). In fact, calling _S_get_pool before the pool is initialized could be seen as a bug somehow. Removing these useless __mt_alloc constructors would speed up both compile time and execution time of programs using STL containers. The pool would then be created by _S_initialize_once the first time allocate is called.
Some additional information. Looking through the CVS log, it appears the __mt_alloc constructors were empty in GCC 3.4, and they were filled when fixing PR 17780. The patch was huge and the log is a bit sparse as to why this part was needed: "(__mt_alloc::__mt_alloc): Call __policy_type::_S_get_pool." The related thread on the libstdc++ mailing-list does not help either.
Created attachment 9779 [details] Remove gratuitous calls to _S_get_pool in __mt_alloc Since I didn't find any reason for these calls, I removed them (see attached patch) and ran a few tests. The following testcase has been compiled at -O3 -march=pentium3. #include <list> int main() { for(int j = 0; j < 10000000; ++j) { std::list<int> a, b, c; std::list<double> d, e, f; std::list<char> g, h, i; } } Without the calls, the list creation is 70% faster: 2.2s instead of 3.7s on my computer. When adding an element into each list at each iteration, there still is a 15% speedup: 15.4s instead of 17.8s. So the cost of these calls to _S_get_pool is not negligible. And the other STL containers are affected as well, not just std::list.
I suspect this is an oversight from early patches of PR 17780. I'll look at this. -benjamin
Subject: Bug 23956 CVSROOT: /cvs/gcc Module name: gcc Changes by: bkoz@gcc.gnu.org 2005-09-22 08:48:33 Modified files: libstdc++-v3 : ChangeLog libstdc++-v3/include/ext: mt_allocator.h Log message: 2005-09-21 Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> PR libstdc++/23956 * include/ext/mt_allocator.h: Remove excess policy_type::_S_get_pool calls in constructors. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.3110&r2=1.3111 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/ext/mt_allocator.h.diff?cvsroot=gcc&r1=1.48&r2=1.49
in on mainline, queued for 4.0.3
Subject: Bug 23956 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-4_0-branch Changes by: bkoz@gcc.gnu.org 2005-09-30 20:41:41 Modified files: libstdc++-v3 : ChangeLog libstdc++-v3/include/ext: mt_allocator.h Log message: 2005-09-30 Guillaume Melquiond <guillaume.melquiond@ens-lyon.fr> PR libstdc++/23956 * include/ext/mt_allocator.h: Remove excess policy_type::_S_get_pool calls in constructors. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.2917.2.89&r2=1.2917.2.90 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/ext/mt_allocator.h.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.45.8.3&r2=1.45.8.4
Fixed in 4.0.3.