libstdc++/7445: poor performance of std::locale::classic() in multi-threaded applications
Alex Kompel
shurik@sequoiap.com
Tue Nov 19 18:16:00 GMT 2002
The following reply was made to PR libstdc++/7445; it has been noted by GNATS.
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--
More information about the Gcc-prs
mailing list