This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Avoid divisions is __mt_alloc::deallocate
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Fri, 02 Apr 2004 11:44:20 +0200
- Subject: [Patch] Avoid divisions is __mt_alloc::deallocate
Hi,
this patchlet rearranges the arithmetic in order to avoid computing
two expensive divisions at each deallocation: now only one at each
removal of a bunch of blocks (~ 1/1000). Yesterday, I enjoyed *so*
much this little thread:
http://sources.redhat.com/ml/libc-alpha/2004-03/msg00301.html
and became even more sensitive to the issue (*) ...
Of course I have checked that there are no risks of overflows.
The existing comments were not particularly clear, I will work on that
in follow on work.
By the way, there is also a correctness bit in it: we were using 'int'
which is too small (32 bits) on 64-bit machines.
Regtested x86-linux, will commit later today.
Paolo.
(*) I'm planning to survey the whole library for that.
////////////
2004-04-02 Paolo Carlini <pcarlini@suse.de>
* include/ext/mt_allocator.h (__mt_alloc<>::deallocate):
Rearrange arithmetic to avoid computing two divisions at
each deallocation.
diff -urN libstdc++-v3-orig/include/ext/mt_allocator.h libstdc++-v3/include/ext/mt_allocator.h
--- libstdc++-v3-orig/include/ext/mt_allocator.h 2004-04-01 17:21:33.000000000 +0200
+++ libstdc++-v3/include/ext/mt_allocator.h 2004-04-02 11:21:53.000000000 +0200
@@ -434,25 +434,23 @@
#ifdef __GTHREADS
if (__gthread_active_p())
{
- // Calculate the number of records to remove from our freelist.
+ // Calculate the number of records to remove from our freelist:
+ // in order to avoid too much contention we wait until the
+ // number of records is "high enough".
const size_t __thread_id = _S_get_thread_id();
- int __remove = (__bin._M_free[__thread_id]
- - (__bin._M_used[__thread_id]
- / _S_options._M_freelist_headroom));
-
- // The calculation above will almost always tell us to
- // remove one or two records at a time, but this creates too
- // much contention when locking and therefore we wait until
- // the number of records is "high enough".
- int __cond1 = static_cast<int>(100 * (_S_bin_size - __which));
- int __cond2 = static_cast<int>(__bin._M_free[__thread_id]
- / _S_options._M_freelist_headroom);
- if (__remove > __cond1 && __remove > __cond2)
+
+ long __remove = ((__bin._M_free[__thread_id]
+ * _S_options._M_freelist_headroom)
+ - __bin._M_used[__thread_id]);
+ if (__remove > (100 * (_S_bin_size - __which)
+ * _S_options._M_freelist_headroom)
+ && __remove > static_cast<long>(__bin._M_free[__thread_id]))
{
__gthread_mutex_lock(__bin._M_mutex);
_Block_record* __tmp = __bin._M_first[__thread_id];
_Block_record* __first = __tmp;
- const int __removed = __remove;
+ __remove /= _S_options._M_freelist_headroom;
+ const long __removed = __remove;
while (__remove > 1)
{
__tmp = __tmp->_M_next;