1 // Copyright (C) 2004 Free Software Foundation, Inc.
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2, or (at your option)
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING. If not, write to the Free
16 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction. Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License. This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
29 * The goal with this application is to compare the performance of
30 * different allocators in a simple producer-consumer scenario.
33 // 2004-02-04 Felix Yen <fwy@alumni.brown.edu>
41 #include <ext/mt_allocator.h>
42 #include <ext/new_allocator.h>
43 #include <ext/malloc_allocator.h>
44 #include <ext/bitmap_allocator.h>
45 #include <ext/pool_allocator.h>
47 #include <testsuite_performance.h>
51 using __gnu_cxx::__mt_alloc
;
52 using __gnu_cxx::new_allocator
;
53 using __gnu_cxx::malloc_allocator
;
54 using __gnu_cxx::bitmap_allocator
;
55 using __gnu_cxx::__pool_alloc
;
56 using abi::__cxa_demangle
;
58 typedef int test_type
;
59 typedef less
<test_type
> compare_type
;
60 typedef malloc_allocator
<test_type
> malloc_alloc_type
;
61 typedef new_allocator
<test_type
> new_alloc_type
;
62 typedef __mt_alloc
<test_type
> so_alloc_type
;
63 typedef bitmap_allocator
<test_type
> bit_alloc_type
;
64 typedef __pool_alloc
<test_type
> po_alloc_type
;
66 typedef pair
<const test_type
, test_type
> pair_type
;
67 typedef malloc_allocator
<pair_type
> malloc_pair_alloc_type
;
68 typedef new_allocator
<pair_type
> new_pair_alloc_type
;
69 typedef __mt_alloc
<pair_type
> so_pair_alloc_type
;
70 typedef bitmap_allocator
<pair_type
> bit_pair_alloc_type
;
71 typedef __pool_alloc
<pair_type
> po_pair_alloc_type
;
73 // The number of iterations to be performed.
74 int iterations
= 10000;
76 // TODO - restore Stefan's comment? i don't understand it. -- fwy
77 int insert_values
= 128;
82 Lock() {pthread_mutex_init(&mutex
, 0);}
83 ~Lock() {pthread_mutex_destroy(&mutex
);}
86 inline pthread_mutex_t
* operator&() {return &mutex
;}
89 inline void lock() {pthread_mutex_lock(&mutex
);}
90 inline void unlock() {pthread_mutex_unlock(&mutex
);}
94 Lock
& operator=(Lock
&);
97 pthread_mutex_t mutex
;
103 AutoLock(Lock
& _lock
)
107 ~AutoLock() {lock
.unlock();}
111 AutoLock
& operator=(AutoLock
&);
117 template<typename Container
>
121 Queue() {pthread_cond_init(&condition
, 0);}
122 ~Queue() {pthread_cond_destroy(&condition
);}
125 void push_back(const typename
Container::value_type
& x
);
126 void swap(Container
& container
);
129 pthread_cond_t condition
;
134 template<typename Container
>
136 Queue
<Container
>::push_back(const typename
Container::value_type
& value
)
138 AutoLock
auto_lock(lock
);
139 const bool signal
= queue
.empty();
140 queue
.insert(queue
.end(), value
);
141 if (signal
) pthread_cond_signal(&condition
);
144 template<typename Container
>
146 Queue
<Container
>::swap(Container
& container
)
148 AutoLock
auto_lock(lock
);
149 while (queue
.empty()) pthread_cond_wait(&condition
, &lock
);
150 queue
.swap(container
);
155 // NB: Make this the last data member of an object defining operator()().
160 Attributes(int state
= PTHREAD_CREATE_JOINABLE
);
161 ~Attributes() {pthread_attr_destroy(&attributes
);}
164 inline pthread_attr_t
* operator&() {return &attributes
;}
167 pthread_attr_t attributes
;
171 Thread() {thread
= pthread_self();}
175 template <typename ThreadOwner
>
176 void create(ThreadOwner
* owner
);
182 Thread::Attributes::Attributes(int state
)
184 pthread_attr_init(&attributes
);
185 pthread_attr_setdetachstate(&attributes
, state
);
190 if (!pthread_equal(thread
, pthread_self()))
191 pthread_join(thread
, 0);
194 template<typename ThreadOwner
>
196 create_thread(void* _this
)
198 ThreadOwner
* owner
= static_cast<ThreadOwner
*>(_this
);
203 template<typename ThreadOwner
>
205 Thread::create(ThreadOwner
* owner
)
207 Thread::Attributes attributes
;
208 pthread_create(&thread
, &attributes
, create_thread
<ThreadOwner
>, owner
);
211 template<typename Container
>
215 Consumer(Queue
<Container
>& _queue
)
217 {thread
.create(this);}
223 Queue
<Container
>& queue
;
227 template<typename Container
>
229 Consumer
<Container
>::operator()()
231 for (int j
= insert_values
* iterations
; j
> 0;)
234 queue
.swap(container
);
235 j
-= container
.size();
239 template<typename TestType
>
240 struct Value
: public pair
<TestType
, TestType
>
243 : pair
<TestType
, TestType
>(0, 0)
246 inline Value
operator++() {return ++this->first
, *this;}
247 inline operator TestType() const {return this->first
;}
250 template<typename Container
>
251 class ProducerConsumer
: private Queue
<Container
>
254 ProducerConsumer() {thread
.create(this);}
263 template<typename Container
>
265 ProducerConsumer
<Container
>::operator()()
267 Consumer
<Container
> consumer(*this);
268 Value
<test_type
> test_value
;
269 for (int j
= insert_values
* iterations
; j
-- > 0;)
270 this->push_back(++test_value
);
273 template<typename Container
>
275 test_container(Container obj
)
277 using namespace __gnu_test
;
281 resource_counter resource
;
283 clear_counters(time
, resource
);
284 start_counters(time
, resource
);
286 ProducerConsumer
<Container
> pc1
;
287 ProducerConsumer
<Container
> pc2
;
289 stop_counters(time
, resource
);
291 std::ostringstream comment
;
292 comment
<< "iterations: " << iterations
<< '\t';
293 comment
<< "type: " << __cxa_demangle(typeid(obj
).name(), 0, 0, &status
);
294 report_header(__FILE__
, comment
.str());
295 report_performance(__FILE__
, string(), time
, resource
);
301 test_container(vector
<test_type
, malloc_alloc_type
>());
304 test_container(vector
<test_type
, new_alloc_type
>());
307 test_container(vector
<test_type
, so_alloc_type
>());
310 test_container(vector
<test_type
, bit_alloc_type
>());
313 test_container(vector
<test_type
, po_alloc_type
>());
317 test_container(list
<test_type
, malloc_alloc_type
>());
320 test_container(list
<test_type
, new_alloc_type
>());
323 test_container(list
<test_type
, so_alloc_type
>());
326 test_container(list
<test_type
, bit_alloc_type
>());
329 test_container(list
<test_type
, po_alloc_type
>());
333 test_container(map
<test_type
, test_type
, compare_type
,
334 malloc_pair_alloc_type
>());
337 test_container(map
<test_type
, test_type
, compare_type
,
338 new_pair_alloc_type
>());
341 test_container(map
<test_type
, test_type
, compare_type
,
342 so_pair_alloc_type
>());
345 test_container(map
<test_type
, test_type
, compare_type
,
346 bit_pair_alloc_type
>());
349 test_container(map
<test_type
, test_type
, compare_type
,
350 po_pair_alloc_type
>());