This is the mail archive of the 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]

Re: Reduce libstdc++-v3 locale::locale() lock contention

>> Ok, I see. I was thinking that in fact, with the patch applied, people
>> not actually using locales pay essentially only an atomic increment.
>> Certainly we can't do better if we still want to use reference counting.
>> Seems a very nice improvement a anyway.
> Actually, if the point is optimizing for the classic locale, which is
> always a nice thing to do, then we could probably do away with reference
> counting altogether: I should check, but since the locale lives in
> statically allocated memory, created in it via placement new, and is
> never actually destroyed, all this reference counting is rather
> pointless (that reminds me the relatively recent trick we added to our
> reference counted string for the trivial string consisting only of '\0',
> it isn't reference counted at all, and indeed when Nathan proposed the
> patch the goal was exactly reducing contention and improving performance
> when different threads concurrently create default constructed strings
> (*)). I don't know which are the tricky issues involved, but I'm coming
> to the conclusion that for "C" we *can* do better. What do you think?
> Paolo.
> (*) Then in the case of basic_string this statically allocated object
> creates some problems from time to time, but the issues are rather moot
> because in the next ABI we will not use reference counting at all. But
> the "C" locale seems a different case, because we are working under the
> assumption that the actual locale is statically allocated anyway, we are
> just talking about reference counting the thing or not.

Actually I was digesting your response and had just finished another patch
(need to build and test) in this area.  The 8 threads case in my test
results shows multi-core scalability issue and it may have to do with cache
line ping-pong.  Here is the preliminary patch (against an old gcc tree ...
will clean it up for gcc trunk next), see if I'm on the right path or not:

Index: libstdc++-v3/include/bits/locale_classes.h
--- libstdc++-v3/include/bits/locale_classes.h.orig     2009-12-17
17:40:06.544613000 +0000
+++ libstdc++-v3/include/bits/locale_classes.h  2009-12-17
18:03:37.905984000 +0000
@@ -505,18 +505,32 @@
     inline void
     _M_add_reference() throw()
-    { __gnu_cxx::__atomic_add(&_M_refcount, 1); }
+    {
+      // Do not do reference counting for C locale objects.
+      // This avoids cache line ping-pong in MT context.
+      // All C locale objects share the same underlying _M_impl,
+      // _S_classic, that is initialized in locale::_S_initialize_once().
+      // Also _S_classic starts with _M_refcount 2.
+      if (this != locale::classic()._M_impl)
+        {
+          __gnu_cxx::__atomic_add(&_M_refcount, 1);
+        }
+    }
     inline void
     _M_remove_reference() throw()
-      if (__gnu_cxx::__exchange_and_add(&_M_refcount, -1) == 1)
-       {
-         try
-           { delete this; }
-         catch(...)
-           { }
-       }
+      // Do not do reference counting for C locale objects.
+      if (this != locale::classic()._M_impl)
+        {
+          if (__gnu_cxx::__exchange_and_add(&_M_refcount, -1) == 1)
+           {
+             try
+               { delete this; }
+             catch(...)
+               { }
+           }
+        }
     _Impl(const _Impl&, size_t);

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