This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]