Bug 40088

Summary: Creating a std::ostringstream object locks a global mutex
Product: gcc Reporter: David White <davewx7>
Component: libstdc++Assignee: Paolo Carlini <paolo.carlini>
Status: RESOLVED FIXED    
Severity: normal CC: bkoz, gcc-bugs, jackie.rosen
Priority: P3    
Version: 4.3.3   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2009-05-10 10:14:14

Description David White 2009-05-10 04:44:57 UTC
When a std::ostringstream object is created, it references a locale object which is synchronized by a global mutex.

This causes a significant performance problem for multi-threaded applications running on systems with many CPU's if they use string streams frequently.
Comment 1 Paolo Carlini 2009-05-10 09:40:26 UTC
System type? More generally, please provide all the informations detailed in:

  http://gcc.gnu.org/bugs.html

Thanks.
Comment 2 Paolo Carlini 2009-05-10 10:14:14 UTC
It's the default contructor of std::locale.
Comment 3 Paolo Carlini 2009-05-10 10:42:27 UTC
David, are you aware of implementations not affected by this problem while providing thread-safe locale::locale() and locale::global, thus much smarter in the way ios_base deals with locale or you have a feeling it's just that a thread-safe global locale doesn't play well with multi-threading?
Comment 4 Richard Biener 2009-05-10 11:52:54 UTC
Hm.  I wonder how the "global" locale is supposed to interact with multiple
threads anyway (in the face of C++ not knowing about threads).  Would it be
a conforming implementation to put the global locale into thread-local storage
(thus, having a "global" locale for each thread)?
Comment 5 Richard Biener 2009-05-10 12:12:36 UTC
Btw, from a quick look the global mutex could be easily replaced with
atomic updates of the reference counts (it seems they already are
atomic) and atomic exchanges of the locale pointer.

Atomically fetching the current global locale and adding a reference to it
(huh, it looks like we leak locales that become global?  at lest we do not
drop references from the global locale we replace in locale::global(const locale&)) is easy (pointer reads are atomic if the pointer is naturally
aligned) - a special case would appear if we ever can get a stale (zero
reference) locale pointer, but that doesn't seem to be the case (see the
previous comment in parens).
Comment 6 Richard Biener 2009-05-10 12:14:38 UTC
Thus, I was meaning to say that

Index: src/locale_init.cc
===================================================================
--- src/locale_init.cc	(revision 147329)
+++ src/locale_init.cc	(working copy)
@@ -208,9 +208,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   locale::locale() throw() : _M_impl(0)
   { 
     _S_initialize();
-    __gnu_cxx::__scoped_lock sentry(get_locale_mutex());
-    _S_global->_M_add_reference();
     _M_impl = _S_global;
+    _M_impl->_M_add_reference();
   }
 
   locale


looks safe apart on architectures where the pointer read can ever return
partially updated values (none I know has this problem).
Comment 7 Richard Biener 2009-05-10 12:21:10 UTC
I should scroll down - ignore my comments.
Comment 8 Paolo Carlini 2009-05-10 12:34:34 UTC
:) In any case, before attempting anything here, I recommend also re-analyzing libstdc++/12658.
Comment 9 Greg Falcon 2009-05-22 21:03:06 UTC
(In reply to comment #4)
> Hm.  I wonder how the "global" locale is supposed to interact with multiple
> threads anyway (in the face of C++ not knowing about threads).  Would it be
> a conforming implementation to put the global locale into thread-local storage
> (thus, having a "global" locale for each thread)?

Pre C++0x, the standard says nothing about threads at all.

The C++0x draft has this to say:
Whether there is one global locale object for the entire program or one global locale object per thread is implementation defined. Implementations are encouraged but not required to provide one global locale object per thread. If there is a single global locale object for the entire program, implementations are not required to avoid data races on it

Comment 10 Paolo Carlini 2009-06-07 11:07:13 UTC
Benjamin, do you have a strong opinion about this issue? I don't, really, but especially in the light of the C++0x drafts (thanks to Greg for pointing it out), I would close for now the issue with a patch adding a configure time option to not use the mutex, the current safe but slow behavior as default, probably.

If I'm not mistaken, in either case the *.so would be binary compatible anyway.

In the future, we should probably move to the one global locale per thread, but I don't think it's easily implementable without affecting the ABI...
Comment 11 paolo@gcc.gnu.org 2009-12-18 09:41:22 UTC
Subject: Bug 40088

Author: paolo
Date: Fri Dec 18 09:41:03 2009
New Revision: 155342

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=155342
Log:
2009-12-18  Jimmy Guo  <jguo@yahoo-inc.com>

	PR libstdc++/40088
	* src/locale_init.cc (locale::locale()): Optimize the common case
	where _S_global still points to _S_classic.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/condition_variable
    trunk/libstdc++-v3/src/locale_init.cc
    trunk/libstdc++-v3/testsuite/30_threads/condition_variable/cons/assign_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/condition_variable/cons/copy_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/condition_variable/members/1.cc
    trunk/libstdc++-v3/testsuite/30_threads/condition_variable/members/2.cc
    trunk/libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/assign_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/condition_variable_any/cons/copy_neg.cc

Comment 12 Paolo Carlini 2009-12-18 09:51:38 UTC
David, I committed a patch which should alleviate the problem, any chance you can tell us whether you are seeing an improvement?

More tweaks (within the C++0x model still) are possible, but seems hard to implement without breaking the (generalized) ABI compatibility:

  http://gcc.gnu.org/ml/libstdc++/2009-12/msg00067.html
Comment 13 Paolo Carlini 2009-12-18 09:57:58 UTC
I meant C++03, sorry.
Comment 14 Paolo Carlini 2009-12-22 10:09:05 UTC
I think this PR can be closed: if the program doesn't change the global locale the mutex is not used anymore, is only incremented a reference count. As an enhancement we can do better, indeed, but the issues are known by now.
Comment 15 Jackie Rosen 2014-02-16 10:02:34 UTC
*** Bug 260998 has been marked as a duplicate of this bug. ***
Seen from the domain http://volichat.com
Marked for reference. Resolved as fixed @bugzilla.