From 78aa145d9ecdbcacc8f9a06022feb3a8f8e2dab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Dumont?= Date: Sun, 29 Jul 2012 16:44:18 +0000 Subject: [PATCH] re PR libstdc++/54075 ([4.7.1] unordered_map insert still slower than 4.6.2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2012-07-29 François Dumont PR libstdc++/54075 * include/bits/hashtable_policy.h (_Prime_rehash_policy::_M_next_bkt): Add a growth factor set to 2 to boost growth in the number of buckets. * testsuite/performance/23_containers/insert/unordered_set.cc: New. From-SVN: r189938 --- libstdc++-v3/ChangeLog | 8 ++++ libstdc++-v3/include/bits/hashtable_policy.h | 31 +++++++------- .../23_containers/insert/unordered_set.cc | 42 +++++++++++++++++++ 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 libstdc++-v3/testsuite/performance/23_containers/insert/unordered_set.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 407b061a827..6d6c06b5f78 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2012-07-29 François Dumont + + PR libstdc++/54075 + * include/bits/hashtable_policy.h + (_Prime_rehash_policy::_M_next_bkt): Add a growth factor set to 2 + to boost growth in the number of buckets. + * testsuite/performance/23_containers/insert/unordered_set.cc: New. + 2012-07-25 François Dumont PR libstdc++/54075 diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index c0a6df5db23..27790f24a5e 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -395,6 +395,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 }; + static const std::size_t _S_growth_factor = 2; + float _M_max_load_factor; mutable std::size_t _M_prev_resize; mutable std::size_t _M_next_resize; @@ -415,28 +417,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static const unsigned char __fast_bkt[12] = { 2, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 }; - if (__n <= 11) + const std::size_t __grown_n = __n * _S_growth_factor; + if (__grown_n <= 11) { _M_prev_resize = 0; _M_next_resize - = __builtin_ceil(__fast_bkt[__n] * (long double)_M_max_load_factor); - return __fast_bkt[__n]; + = __builtin_ceil(__fast_bkt[__grown_n] + * (long double)_M_max_load_factor); + return __fast_bkt[__grown_n]; } - const unsigned long* __p - = std::lower_bound(__prime_list + 5, __prime_list + _S_n_primes, __n); + const unsigned long* __next_bkt + = std::lower_bound(__prime_list + 5, __prime_list + _S_n_primes, + __grown_n); + const unsigned long* __prev_bkt + = std::lower_bound(__prime_list + 1, __next_bkt, __n / _S_growth_factor); - // Shrink will take place only if the number of elements is small enough - // so that the prime number 2 steps before __p is large enough to still - // conform to the max load factor: _M_prev_resize - = __builtin_floor(*(__p - 2) * (long double)_M_max_load_factor); - - // Let's guaranty that a minimal grow step of 11 is used - if (*__p - __n < 11) - __p = std::lower_bound(__p, __prime_list + _S_n_primes, __n + 11); - _M_next_resize = __builtin_ceil(*__p * (long double)_M_max_load_factor); - return *__p; + = __builtin_floor(*(__prev_bkt - 1) * (long double)_M_max_load_factor); + _M_next_resize + = __builtin_ceil(*__next_bkt * (long double)_M_max_load_factor); + return *__next_bkt; } // Return the smallest prime p such that alpha p >= n, where alpha diff --git a/libstdc++-v3/testsuite/performance/23_containers/insert/unordered_set.cc b/libstdc++-v3/testsuite/performance/23_containers/insert/unordered_set.cc new file mode 100644 index 00000000000..83d3935956b --- /dev/null +++ b/libstdc++-v3/testsuite/performance/23_containers/insert/unordered_set.cc @@ -0,0 +1,42 @@ +// Copyright (C) 2012 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=c++11" } + +#include +#include + +int main() +{ + using namespace __gnu_test; + + time_counter time; + resource_counter resource; + + const int sz = 10000000; + + std::unordered_set s; + start_counters(time, resource); + + for (int i = 0; i != sz ; ++i) + s.insert(i); + + stop_counters(time, resource); + report_performance(__FILE__, "unordered_set 10000000 insertions", + time, resource); + return 0; +}