Bug 7445 - poor performance of std::locale::classic() in multi-threaded applications
Summary: poor performance of std::locale::classic() in multi-threaded applications
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 3.1.1
: P3 normal
Target Milestone: ---
Assignee: Loren Rittle
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-07-30 11:46 UTC by shurik
Modified: 2003-07-25 17:33 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
7445.cc (1.03 KB, application/octet-stream)
2003-05-21 15:17 UTC, shurik
Details

Note You need to log in before you can comment on or make changes to this bug.
Description shurik 2002-07-30 11:46:00 UTC
poor performance of std::locale::classic() in multi-threaded applications. std::locale:classic() is using _STL_auto_lock too extensively. It should only be used when the locale object is initialized. It does locks the mutex
on every call at present. See the fix below.

Release:
gcc version 3.1.1

Environment:
RedHat Linux 7.3
Comment 1 shurik 2002-07-30 11:46:00 UTC
Fix:
*** libstdc++-v3/src/locale.old Tue Jul 30 11:31:01 2002
--- libstdc++-v3/src/locale.cc  Tue Jul 30 11:31:13 2002
***************
*** 285,294 ****
    locale::classic()
    {
      static _STL_mutex_lock __lock __STL_MUTEX_INITIALIZER;
-     _STL_auto_lock __auto(__lock);

      if (!_S_classic)
        {
        try
          {
            // 26 Standard facets, 2 references.
--- 285,294 ----
    locale::classic()
    {
      static _STL_mutex_lock __lock __STL_MUTEX_INITIALIZER;

      if (!_S_classic)
        {
+         _STL_auto_lock __auto(__lock);
        try
          {
            // 26 Standard facets, 2 references.
Comment 2 Benjamin Kosnik 2002-07-31 12:35:31 UTC
Responsible-Changed-From-To: unassigned->bkoz
Responsible-Changed-Why: Mine.
Comment 3 Benjamin Kosnik 2002-07-31 12:35:31 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Something similar checked in to gcc sources. Thanks!
    
    -benjamin
Comment 4 Benjamin Kosnik 2002-07-31 19:34:09 UTC
From: bkoz@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/7445
Date: 31 Jul 2002 19:34:09 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Changes by:	bkoz@gcc.gnu.org	2002-07-31 12:34:09
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	libstdc++-v3/docs/html: abi.txt 
 	libstdc++-v3/docs/html/22_locale: howto.html 
 	libstdc++-v3/src: locale.cc 
 
 Log message:
 	2002-07-31  Simon Whomsley  <whomsley@avacadcam.com>
 	
 	* docs/html/22_locale/howto.html: Fix.
 	
 	2002-07-31  Alex Kompel  <shurik@sequoiap.com>
 	
 	PR libstdc++/7445
 	* src/locale.cc (locale::classic): Move locks inside !_S_classic
 	block.
 	
 	2002-07-31  Benjamin Kosnik  <bkoz@redhat.com>
 	
 	* docs/html/abi.txt: Update.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.1298&r2=1.1299
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/docs/html/abi.txt.diff?cvsroot=gcc&r1=1.3&r2=1.4
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/docs/html/22_locale/howto.html.diff?cvsroot=gcc&r1=1.11&r2=1.12
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/src/locale.cc.diff?cvsroot=gcc&r1=1.61&r2=1.62
 

Comment 5 Jakub Jelinek 2002-08-01 21:29:19 UTC
From: jakub@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/7445
Date: 1 Aug 2002 21:29:19 -0000

 CVSROOT:	/cvs/gcc
 Module name:	egcs
 Branch: 	gcc-3_2-branch
 Changes by:	jakub@gcc.gnu.org	2002-08-01 14:29:18
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	gcc/testsuite  : ChangeLog 
 	gcc/testsuite/g++.old-deja/g++.abi: ptrflags.C 
 	libstdc++-v3/config: linker-map.gnu 
 	libstdc++-v3/docs/html/22_locale: howto.html 
 	libstdc++-v3/src: Makefile.am Makefile.in locale-inst.cc 
 	                  locale.cc 
 	libstdc++-v3/testsuite/21_strings: capacity.cc 
 	libstdc++-v3/testsuite/22_locale: 
 	                                  codecvt_members_unicode_char.cc 
 	                                  codecvt_members_unicode_wchar_t.cc 
 	                                  ctor_copy_dtor.cc 
 	libstdc++-v3/testsuite/27_io: filebuf.cc filebuf_virtuals.cc 
 	                              fstream.cc ios_init.cc istream.cc 
 	                              ostream.cc streambuf.cc 
 	                              stringbuf.cc stringstream.cc 
 	libstdc++-v3/testsuite: testsuite_hooks.h 
 	libstdc++-v3/include/bits: fpos.h char_traits.h fstream.tcc 
 	                           istream.tcc locale_facets.h 
 	                           locale_facets.tcc ostream.tcc 
 	                           sstream.tcc streambuf_iterator.h 
 	libstdc++-v3/include/std: std_fstream.h std_streambuf.h 
 	libstdc++-v3/libsupc++: cxxabi.h tinfo.cc tinfo2.cc 
 Added files:
 	libstdc++-v3/src: fstream.cc 
 
 Log message:
 	2002-08-01  Benjamin Kosnik   <bkoz@redhat.com>
 	
 	* g++.old-deja/g++.abi/ptrflags.C (expect): Change
 	__qualifier_flags to __flags.
 	
 	2002-08-01  Benjamin Kosnik  <bkoz@redhat.com>
 	Jakub Jelinek  <jakub@redhat.com>
 	
 	* config/linker-map.gnu: Change CXXABI_1 to CXXABI_1.2,
 	GLIBCPP_3.1 to GLIBCPP_3.2.
 	
 	2002-07-31  Benjamin Kosnik  <bkoz@redhat.com>
 	Mark Mitchell  <mark@codesourcery.com>
 	
 	PR libstdc++/7442
 	* libsupc++/cxxabi.h (class __base_class_type_info::hwm_bit):
 	Change to __hwm_bit.
 	(__class_type_info): And here.
 	
 	2002-07-31  Benjamin Kosnik  <bkoz@redhat.com>
 	
 	PR libstdc++/7442
 	* libsupc++/cxxabi.h
 	(__base_class_info): Change to __base_class_type_info. 2.9.5p6c
 	(__base_class_info::__base): Change to __base_type. 2.9.5p6c
 	(__base_class_info::offset_shift): Change to __offset_shift. 2.9.5p6c
 	(__vmi_class_type_info::__base_info): Don't make const, of type
 	__base_class_type_info, as per 2.9.5p6c
 	(__pbase_type_info::__qualifier_flags): Change to __flags, as per
 	2.9.5p7.
 	(__pbase_type_info::__qualifier_masks): Change to __masks, as per
 	2.9.5p7.
 	(__pointer_to_member_type_info::__context_class): Change member to
 	__context, as per 2.9.5p9.
 	* libsupc++/tinfo2.cc (__pointer_catch): Change __context_class to
 	__context.
 	* libsupc++/tinfo2.cc (__do_catch): Change __qualifier_flags to
 	__flags.
 	* libsupc++/tinfo.cc (__do_find_public_src): Change __base to
 	__base_type.
 	* libsupc++/tinfo.cc (__do_dyncast): Same.
 	* libsupc++/tinfo.cc (__do_upcast): Same.
 	
 	2002-07-31  Simon Whomsley  <whomsley@avacadcam.com>
 	
 	* docs/html/22_locale/howto.html: Fix.
 	
 	2002-07-31  Alex Kompel  <shurik@sequoiap.com>
 	
 	PR libstdc++/7445
 	* src/locale.cc (locale::classic): Move locks inside !_S_classic
 	block.
 	
 	2002-07-30  Benjamin Kosnik  <bkoz@redhat.com>
 	Gabriel Dos Reis  <gdr@nerim.net>
 	
 	* include/bits/char_traits.h: Remove generic definitions.
 	* include/bits/streambuf_iterator.h (istreambuf_iterator): Use
 	eof, not -2.
 	* include/bits/istream.tcc (istream::readsome): Don't check
 	against eof, instead use constants.
 	(istream::sync): Same.
 	(istream::sentry::sentry): Use eq_int_type.
 	(istream::get): Same.
 	* include/bits/ostream.tcc: Change __pad to
 	__pad<_CharT, _Traits>::_S_pad.
 	* include/bits/locale_facets.h: Add __pad_traits generic and
 	ostreambuf_iterator specialization.
 	* include/bits/locale_facets.tcc: Change __pad into struct __pad
 	with a _CharT and _Traits template parameter and _S_pad static
 	member function.
 	* src/locale-inst.cc: Update __pad instantiations.
 	
 	* include/std/std_fstream.h: Declare _M_underflow_common
 	specializations.
 	* src/fstream.cc: New. Add _M_underflow_common specializations.
 	* include/bits/fstream.tcc (filebuf::close): Use traits_type.
 	(filebuf::_M_underflow_common(bool)): Remove generic version, as
 	sys_ungetc and custom int_types don't get along.
 	* include/std/std_streambuf.h: Add _M_pos.
 	* src/Makefile.am (sources): Add fstream.cc.
 	* src/Makefile.in: Regenerate.
 	
 	* testsuite/21_strings/capacity.cc: Add char_traits specializations.
 	* testsuite/22_locale/codecvt_members_unicode_char.cc: Same.
 	* testsuite/22_locale/codecvt_members_unicode_wchar_t.cc: Same.
 	* testsuite/22_locale/ctor_copy_dtor.cc: Same.
 	* testsuite/27_io/filebuf_virtuals.cc (test07): Move to...
 	* testsuite/27_io/filebuf.cc: ...here.
 	* testsuite/testsuite_hooks.h: Add gnu_char, gnu_int, char_traits
 	specialization for both.
 	* testsuite/27_io/streambuf.cc: Add instantiation test,
 	testsuite_hooks include.
 	* testsuite/27_io/istream.cc: Same.
 	* testsuite/27_io/ostream.cc: Same.
 	* testsuite/27_io/fstream.cc: Same.
 	* testsuite/27_io/stringstream.cc: Same.
 	* testsuite/27_io/filebuf.cc: Same.
 	* testsuite/27_io/stringbuf.cc: Same.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1057.2.159.2.1&r2=1.1057.2.159.2.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1672.2.166.2.1&r2=1.1672.2.166.2.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/testsuite/g++.old-deja/g++.abi/ptrflags.C.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.5&r2=1.5.30.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/config/linker-map.gnu.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.5.2.6&r2=1.5.2.6.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/docs/html/22_locale/howto.html.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.11&r2=1.11.14.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/src/fstream.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=NONE&r2=1.2.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/src/Makefile.am.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.103.2.4&r2=1.103.2.4.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/src/Makefile.in.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.144.2.6&r2=1.144.2.6.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/src/locale-inst.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.29.2.5&r2=1.29.2.5.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/src/locale.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.54.2.6.4.1&r2=1.54.2.6.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/21_strings/capacity.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.6.2.1&r2=1.6.2.1.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_char.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.2.2.2&r2=1.2.2.2.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_wchar_t.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1.16.1&r2=1.1.16.1.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/22_locale/ctor_copy_dtor.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.13.12.1&r2=1.13.12.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/filebuf.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.18.12.1&r2=1.18.12.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.4.2.2&r2=1.4.2.2.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/fstream.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1.2.1&r2=1.1.2.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/ios_init.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.4.2.3&r2=1.4.2.3.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/istream.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.4.12.1&r2=1.4.12.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/ostream.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.4.12.1&r2=1.4.12.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/streambuf.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.10.8.1.4.1&r2=1.10.8.1.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/stringbuf.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.7.2.1.4.1&r2=1.7.2.1.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/27_io/stringstream.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.8.12.1&r2=1.8.12.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/testsuite/testsuite_hooks.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.5.2.1&r2=1.5.2.1.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/fpos.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.8&r2=1.8.14.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/char_traits.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.12&r2=1.12.14.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/fstream.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.25.2.12&r2=1.25.2.12.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/istream.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.24.2.6.2.1&r2=1.24.2.6.2.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/locale_facets.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.41.2.2.4.1&r2=1.41.2.2.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/locale_facets.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.63.2.13&r2=1.63.2.13.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/ostream.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.22.2.8&r2=1.22.2.8.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/sstream.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.8.2.2.4.1&r2=1.8.2.2.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/bits/streambuf_iterator.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.5.2.2&r2=1.5.2.2.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/std/std_fstream.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.6.2.6&r2=1.6.2.6.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/include/std/std_streambuf.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.5.2.2.4.1&r2=1.5.2.2.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/libsupc++/cxxabi.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.6&r2=1.6.14.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/libsupc++/tinfo.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.9&r2=1.9.14.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libstdc++-v3/libsupc++/tinfo2.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.6&r2=1.6.26.1
 
Comment 6 Benjamin Kosnik 2002-08-02 09:25:22 UTC
State-Changed-From-To: closed->feedback
State-Changed-Why: No, not fixed...
Comment 7 Benjamin Kosnik 2002-08-08 15:49:18 UTC
Responsible-Changed-From-To: bkoz->ljrittle
Responsible-Changed-Why: I'm going to assign this to you. When/if sourcecode is provided that demonstrates this problem, perhaps you could take a look at it.
    
    I'll revert to the last known good state for now.
    
    -benjamin
Comment 8 Benjamin Kosnik 2002-08-08 15:49:18 UTC
State-Changed-From-To: feedback->analyzed
State-Changed-Why: Reverted, pending suggestion by Loren to have actual code to analyze the problem. You'll have to come up with a self-contained, hopefully minimal test case that clearly shows this problem.
    
    -benjamin
Comment 9 rittle 2002-08-08 18:58:42 UTC
From: Loren James Rittle <rittle@latour.rsch.comm.mot.com>
To: bkoz@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org,
        gcc-prs@gcc.gnu.org, ljrittle@gcc.gnu.org, shurik@sequoiap.com
Cc:  
Subject: Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
Date: Thu, 8 Aug 2002 18:58:42 -0500 (CDT)

 OK, I'd be happy to find a performance fix that doesn't make the
 library code subtly less portable when we have a test case.  A
 reference to code already in our test suite would be acceptable.
 
 I just looked at some locale code in our test suite under gdb and then
 constructed the smallest cases that used std::locale::classic() [1]
 and another that did not [2].  Then, I compiled both [1] and [2] with
 and without -static and looked under gdb.  In all four cases,
 std::locale::classic() was called once before main().
 
 [1]
 #include <locale>
 
 int main (void)
 {
   std::locale::classic();
 }
 
 [2]
 #include <locale>
 
 int main (void)
 {
 }
 
 Benjamin (as the "local locale" expert), is it *always* true that
 std::locale::classic() is called at least once during startup before
 control is transferred to main()?  If so (and will always be so), then
 all thread-related locking could be removed IMHO.  In practice, our
 implementation of the Standard C++ library (with optional threading
 support) already supposes that no thread which uses the library
 implementation may have ever been started before main() is invoked.
 If not true, then this change would make a very hard to detect
 threading bug when the assumption changes.
 
 Regards,
 Loren

Comment 10 Benjamin Kosnik 2002-08-08 23:18:57 UTC
From: Benjamin Kosnik <bkoz@redhat.com>
To: Loren James Rittle <rittle@latour.rsch.comm.mot.com>
Cc: bkoz@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org,
   gcc-prs@gcc.gnu.org, ljrittle@gcc.gnu.org, shurik@sequoiap.com
Subject: Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
Date: Thu, 8 Aug 2002 23:18:57 -0700

 > OK, I'd be happy to find a performance fix that doesn't make the
 > library code subtly less portable when we have a test case.  A
 > reference to code already in our test suite would be acceptable.
 
 Yeah. This is kind of all hand-wavy at this point.
 
 > Benjamin (as the "local locale" expert), is it *always* true that
 > std::locale::classic() is called at least once during startup before
 > control is transferred to main()?  If so (and will always be so), then
 > all thread-related locking could be removed IMHO.  In practice, our
 > implementation of the Standard C++ library (with optional threading
 > support) already supposes that no thread which uses the library
 > implementation may have ever been started before main() is invoked.
 > If not true, then this change would make a very hard to detect
 > threading bug when the assumption changes.
 
 This is true. I would think the lock could then be removed? I'll let you
 figure out what to do with current sources. Thanks for the help.
 
 -benjamin

Comment 11 Benjamin Kosnik 2002-08-15 22:25:40 UTC
From: bkoz@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/7445
Date: 15 Aug 2002 22:25:40 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Changes by:	bkoz@gcc.gnu.org	2002-08-15 15:25:39
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	libstdc++-v3/docs/html/17_intro: TODO 
 	libstdc++-v3/include/bits: fstream.tcc 
 	libstdc++-v3/include/ext: stdio_filebuf.h 
 	libstdc++-v3/src: locale.cc 
 
 Log message:
 	2002-08-15  Benjamin Kosnik  <bkoz@redhat.com>
 	
 	* include/ext/stdio_filebuf.h (stdio_filebuf): Explicitly set
 	_M_buf_size_opt to zero when unbuffering.
 	* include/bits/fstream.tcc (filebuf::showmanyc): Simplify.
 	Consistency checks for _M_buf_size_opt.
 	
 	Revert PR libstdc++/7445
 	* src/locale.cc (locale::classic): Revert.
 	
 	* docs/html/17_intro/TODO: Add.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&r1=1.1319&r2=1.1320
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/docs/html/17_intro/TODO.diff?cvsroot=gcc&r1=1.6&r2=1.7
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/bits/fstream.tcc.diff?cvsroot=gcc&r1=1.39&r2=1.40
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/ext/stdio_filebuf.h.diff?cvsroot=gcc&r1=1.2&r2=1.3
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/src/locale.cc.diff?cvsroot=gcc&r1=1.62&r2=1.63
 

Comment 12 Benjamin Kosnik 2002-08-15 22:51:02 UTC
From: bkoz@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/7445
Date: 15 Aug 2002 22:51:02 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Branch: 	gcc-3_2-branch
 Changes by:	bkoz@gcc.gnu.org	2002-08-15 15:51:02
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	libstdc++-v3/docs/html/17_intro: TODO 
 	libstdc++-v3/include/bits: fstream.tcc 
 	libstdc++-v3/include/ext: stdio_filebuf.h 
 	libstdc++-v3/src: locale.cc 
 
 Log message:
 	2002-08-15  Benjamin Kosnik  <bkoz@redhat.com>
 	
 	* include/ext/stdio_filebuf.h (stdio_filebuf): Explicitly set
 	_M_buf_size_opt to zero when unbuffering.
 	* include/bits/fstream.tcc (filebuf::showmanyc): Simplify.
 	Consistency checks for _M_buf_size_opt.
 	
 	Revert PR libstdc++/7445
 	* src/locale.cc (locale::classic): Revert.
 	
 	* docs/html/17_intro/TODO: Add.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1057.2.159.2.5&r2=1.1057.2.159.2.6
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/docs/html/17_intro/TODO.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.5.2.1&r2=1.5.2.1.4.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/bits/fstream.tcc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.25.2.12.4.1&r2=1.25.2.12.4.2
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/include/ext/stdio_filebuf.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1.2.2&r2=1.1.2.2.2.1
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/src/locale.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.54.2.6.4.2&r2=1.54.2.6.4.3
 
Comment 13 Benjamin Kosnik 2002-11-11 15:12:30 UTC
State-Changed-From-To: analyzed->closed
State-Changed-Why: No more details are forthcoming on this issue. We've needed a test case for more than six months.
    
    Sorry,
    benjamin
Comment 14 shurik 2002-11-11 18:52:18 UTC
From: "Alex Kompel" <shurik@sequoiap.com>
To: <bkoz@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <gcc-prs@gcc.gnu.org>,
   <ljrittle@gcc.gnu.org>, <shurik@sequoiap.com>, <gcc-gnats@gcc.gnu.org>
Cc:  
Subject: Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
Date: Mon, 11 Nov 2002 18:52:18 -0800

 I am a bit confused. Audit trail is kind of hard to read. Have you been
 waiting on something from me?
 
 -alex
 
 ----- Original Message ----- 
 From: <bkoz@gcc.gnu.org>
 To: <gcc-bugs@gcc.gnu.org>; <gcc-prs@gcc.gnu.org>; <ljrittle@gcc.gnu.org>; <shurik@sequoiap.com>
 Sent: Monday, November 11, 2002 3:12 PM
 Subject: Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
 
 
 > Synopsis: poor performance of std::locale::classic() in multi-threaded applications
 > 
 > State-Changed-From-To: analyzed->closed
 > State-Changed-By: bkoz
 > State-Changed-When: Mon Nov 11 15:12:30 2002
 > State-Changed-Why:
 >     No more details are forthcoming on this issue. We've needed a test case for more than six months.
 >     
 >     Sorry,
 >     benjamin
 > 
 > http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7445

Comment 15 Benjamin Kosnik 2002-11-11 22:40:46 UTC
From: Benjamin Kosnik <bkoz@redhat.com>
To: "Alex Kompel" <shurik@sequoiap.com>
Cc: bkoz@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
   ljrittle@gcc.gnu.org, shurik@sequoiap.com, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
Date: Mon, 11 Nov 2002 22:40:46 -0600

 >I am a bit confused. Audit trail is kind of hard to read. Have you been
 >waiting on something from me?
 
 Uh. Yeah.
 
 We need a test case. Provide one and we'll re-open this. I thought I'd
 made this clear, but apparently not.
 
 -benjamin

Comment 16 shurik 2002-11-12 12:48:46 UTC
From: "Alex Kompel" <shurik@sequoiap.com>
To: "Benjamin Kosnik" <bkoz@redhat.com>
Cc: <bkoz@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <gcc-prs@gcc.gnu.org>,
   <ljrittle@gcc.gnu.org>, <gcc-gnats@gcc.gnu.org>
Subject: Re: libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
Date: Tue, 12 Nov 2002 12:48:46 -0800

 This is a multi-part message in MIME format.
 
 ------=_NextPart_000_0063_01C28A49.D6F2B070
 Content-Type: text/plain;
 	charset="iso-8859-1"
 Content-Transfer-Encoding: 7bit
 
 > 
 > >I am a bit confused. Audit trail is kind of hard to read. Have you been
 > >waiting on something from me?
 > 
 > Uh. Yeah.
 > 
 > We need a test case. Provide one and we'll re-open this. I thought I'd
 > made this clear, but apparently not.
 > 
 
 See the attached file. 
 get_locale() is functionally equivalent to std::locale::classic()
 
 ----- test results (RedHat 7.3 2.4.18-17.7.xsmp 2 CPU -----
 [root@epos4 test]# c++ -DDO_LOCK -o test_lock -pthread loc_thr.cpp
 [root@epos4 test]# c++ -o test_nolock -pthread loc_thr.cpp
 [root@epos4 test]# ./test_lock
 Creating thread 0
 Creating thread 1
 Creating thread 2
 Creating thread 3
 Starting sorting...
 Sorting time:    4.08
 Sorting time:    4.02
 Sorting time:    4.26
 Sorting time:    4.21
 [root@epos4 test]# ./test_nolock
 Creating thread 0
 Creating thread 1
 Creating thread 2
 Creating thread 3
 Starting sorting...
 Sorting time:    0.06
 Sorting time:    0.06
 Sorting time:    0.06
 Sorting time:    0.06
 
 ------=_NextPart_000_0063_01C28A49.D6F2B070
 Content-Type: application/octet-stream;
 	name="loc_thr.cpp"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment;
 	filename="loc_thr.cpp"
 
 #include <pthread.h>=0A=
 #include <locale>=0A=
 #include <string>=0A=
 #include <functional>=0A=
 #include <list>=0A=
 =0A=
 #define NUM_THREADS 4=0A=
 #define SORT_SIZE 1000=0A=
 #define NSAMPLES 5=0A=
 const char* samples[NSAMPLES] =3D {=0A=
 	"this is just a test 1",=0A=
 	"THIS IS JUST A TEST 1",=0A=
 	"this IS JUST A TEST 1",=0A=
 	"THIS IS JUST A TEST 2",=0A=
 	"this is just a test 2"=0A=
 };=0A=
 =0A=
 extern const std::locale& get_locale() {=0A=
       static const std::locale* l =3D 0;=0A=
 #ifdef DO_LOCK=0A=
       static std::_STL_mutex_lock __lock __STL_MUTEX_INITIALIZER;=0A=
       std::_STL_auto_lock __auto(__lock);=0A=
       if( !l ) {=0A=
 	 l =3D &std::locale::classic();=0A=
       }=0A=
 #else=0A=
       if( !l ) {=0A=
          static std::_STL_mutex_lock __lock __STL_MUTEX_INITIALIZER;=0A=
          std::_STL_auto_lock __auto(__lock);=0A=
 	 l =3D &std::locale::classic();=0A=
       }=0A=
 #endif=0A=
       return *l;=0A=
 }=0A=
 =0A=
 template <class T>=0A=
 bool lowercase_less( T c1, T c2 ) {=0A=
 	return std::tolower(c1, get_locale()) < std::tolower(c2, get_locale());=0A=
 }=0A=
 =0A=
 template <class T>=0A=
 bool str_case_less(const std::basic_string<T>& s1, const =
 std::basic_string<T>& s2)=0A=
 {=0A=
 	return std::lexicographical_compare(=0A=
 			s1.begin(), s1.end(),=0A=
 			s2.begin(), s2.end(),=0A=
 			std::ptr_fun( lowercase_less<T> )=0A=
 		 );=0A=
 }=0A=
 =0A=
 pthread_mutex_t count_mutex;=0A=
 pthread_cond_t ready_sort;=0A=
 int ready_count =3D 0;=0A=
 =0A=
 typedef std::list<std::string> test_list;=0A=
 void* thread_main( void* ) =0A=
 {=0A=
 	test_list tl;=0A=
 =0A=
 	for( int i=3D0; i<SORT_SIZE; i++ ) {=0A=
 		tl.push_back( samples[i%NSAMPLES] );=0A=
 	}=0A=
 =0A=
     	pthread_mutex_lock(&count_mutex);=0A=
 	if( ++ready_count<NUM_THREADS ) {=0A=
     		pthread_cond_wait(&ready_sort, &count_mutex);=0A=
 	} else {=0A=
 		printf( "Starting sorting...\n" );=0A=
 		pthread_cond_broadcast(&ready_sort);=0A=
 	}=0A=
     	pthread_mutex_unlock(&count_mutex);=0A=
 =0A=
 	clock_t t1, t2;=0A=
 	t1 =3D clock();=0A=
 	tl.sort( str_case_less<char> );=0A=
 	t2 =3D clock();=0A=
 	printf( "Sorting time: %7.2f\n", (float)(t2-t1)/CLOCKS_PER_SEC);=0A=
 	return 0;=0A=
 }=0A=
 =0A=
 =0A=
 int main()=0A=
 {=0A=
 	pthread_t thread[NUM_THREADS];=0A=
    	pthread_attr_t attr;=0A=
 	int t;=0A=
 =0A=
   	/* Initialize mutex and condition variable objects */=0A=
  	pthread_mutex_init(&count_mutex, NULL);=0A=
   	pthread_cond_init(&ready_sort, NULL);=0A=
 =0A=
    	/* Initialize and set thread detached attribute */=0A=
    	pthread_attr_init(&attr);=0A=
    	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);=0A=
 =0A=
    	for(t=3D0;t < NUM_THREADS;t++) {=0A=
       		printf("Creating thread %d\n", t);=0A=
       		pthread_create(&thread[t], &attr, thread_main, NULL); =0A=
    	}=0A=
 =0A=
    	/* Free attribute and wait for the other threads */=0A=
    	for(t=3D0;t < NUM_THREADS;t++) {=0A=
        		pthread_join(thread[t], NULL);=0A=
    	}=0A=
 =0A=
    	pthread_attr_destroy(&attr);=0A=
  	pthread_mutex_destroy(&count_mutex);=0A=
   	pthread_cond_destroy(&ready_sort);=0A=
 =0A=
 	return 0;=0A=
 }=0A=
 
 ------=_NextPart_000_0063_01C28A49.D6F2B070--
 
Comment 17 Benjamin Kosnik 2002-11-12 19:56:30 UTC
State-Changed-From-To: closed->open
State-Changed-Why: Loren, it looks like there is a test case for this now. Can you take a look at this please?
    
    thanks,
    benjamin
Comment 18 Loren Rittle 2002-11-13 06:57:57 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Patch applied to mainline.  Thank you for the report.
    Sorry for the lengthy delay in getting this sorted out.
    Should be safe for 3.2 branch when it reopens but we
    don't usually consider performance patches.
Comment 19 Loren Rittle 2002-12-04 22:24:05 UTC
From: ljrittle@gcc.gnu.org
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: libstdc++/7445
Date: 4 Dec 2002 22:24:05 -0000

 CVSROOT:	/cvs/gcc
 Module name:	gcc
 Branch: 	gcc-3_2-branch
 Changes by:	ljrittle@gcc.gnu.org	2002-12-04 14:24:05
 
 Modified files:
 	libstdc++-v3   : ChangeLog 
 	libstdc++-v3/src: locale.cc 
 
 Log message:
 	PR libstdc++/7445
 	* src/locale.cc (std::locale::classic()): Weaken locking protocol.
 
 Patches:
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.1057.2.159.2.62&r2=1.1057.2.159.2.63
 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libstdc++-v3/src/locale.cc.diff?cvsroot=gcc&only_with_tag=gcc-3_2-branch&r1=1.54.2.6.4.6&r2=1.54.2.6.4.7