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 // The number of iterations to be performed.
67 int iterations = 10000;
69 // TODO - restore Stefan's comment? i don't understand it. -- fwy
70 int insert_values = 128;
75 Lock() {pthread_mutex_init(&mutex, 0);}
76 ~Lock() {pthread_mutex_destroy(&mutex);}
79 inline pthread_mutex_t* operator&() {return &mutex;}
82 inline void lock() {pthread_mutex_lock(&mutex);}
83 inline void unlock() {pthread_mutex_unlock(&mutex);}
87 Lock& operator=(Lock&);
90 pthread_mutex_t mutex;
100 ~AutoLock() {lock.unlock();}
104 AutoLock& operator=(AutoLock&);
110 template<typename Container>
114 Queue() {pthread_cond_init(&condition, 0);}
115 ~Queue() {pthread_cond_destroy(&condition);}
118 void push_back(const typename Container::value_type& x);
119 void swap(Container& container);
122 pthread_cond_t condition;
127 template<typename Container>
129 Queue<Container>::push_back(const typename Container::value_type& value)
131 AutoLock auto_lock(lock);
132 const bool signal = queue.empty();
133 queue.insert(queue.end(), value);
134 if (signal) pthread_cond_signal(&condition);
137 template<typename Container>
139 Queue<Container>::swap(Container& container)
141 AutoLock auto_lock(lock);
142 while (queue.empty()) pthread_cond_wait(&condition, &lock);
143 queue.swap(container);
148 // NB: Make this the last data member of an object defining operator()().
153 Attributes(int state = PTHREAD_CREATE_JOINABLE);
154 ~Attributes() {pthread_attr_destroy(&attributes);}
157 inline pthread_attr_t* operator&() {return &attributes;}
160 pthread_attr_t attributes;
164 Thread() {thread = pthread_self();}
168 template <typename ThreadOwner>
169 void create(ThreadOwner* owner);
175 Thread::Attributes::Attributes(int state)
177 pthread_attr_init(&attributes);
178 pthread_attr_setdetachstate(&attributes, state);
183 if (!pthread_equal(thread, pthread_self()))
184 pthread_join(thread, 0);
187 template<typename ThreadOwner>
189 create_thread(void* _this)
191 ThreadOwner* owner = static_cast<ThreadOwner*>(_this);
196 template<typename ThreadOwner>
198 Thread::create(ThreadOwner* owner)
200 Thread::Attributes attributes;
201 pthread_create(&thread, &attributes, create_thread<ThreadOwner>, owner);
204 template<typename Container>
208 Consumer(Queue<Container>& _queue)
210 {thread.create(this);}
216 Queue<Container>& queue;
220 template<typename Container>
222 Consumer<Container>::operator()()
224 for (int j = insert_values * iterations; j > 0;)
227 queue.swap(container);
228 j -= container.size();
232 template<typename TestType>
233 struct Value : public pair<TestType, TestType>
236 : pair<TestType, TestType>(0, 0)
239 inline Value operator++() {return ++this->first, *this;}
240 inline operator TestType() const {return this->first;}
243 template<typename Container>
244 class ProducerConsumer : private Queue<Container>
247 ProducerConsumer() {thread.create(this);}
256 template<typename Container>
258 ProducerConsumer<Container>::operator()()
260 Consumer<Container> consumer(*this);
261 Value<test_type> test_value;
262 for (int j = insert_values * iterations; j-- > 0;)
263 this->push_back(++test_value);
266 template<typename Container>
268 test_container(Container obj)
270 using namespace __gnu_test;
274 resource_counter resource;
276 clear_counters(time, resource);
277 start_counters(time, resource);
279 ProducerConsumer<Container> pc1;
280 ProducerConsumer<Container> pc2;
282 stop_counters(time, resource);
284 std::ostringstream comment;
285 comment << "iterations: " << iterations << '\t';
286 comment << "type: " << __cxa_demangle(typeid(obj).name(), 0, 0, &status);
287 report_header(__FILE__, comment.str());
288 report_performance(__FILE__, string(), time, resource);
294 test_container(vector<test_type, malloc_alloc_type>());
297 test_container(vector<test_type, new_alloc_type>());
300 test_container(vector<test_type, so_alloc_type>());
303 test_container(vector<test_type, bit_alloc_type>());
306 test_container(vector<test_type, po_alloc_type>());
310 test_container(list<test_type, malloc_alloc_type>());
313 test_container(list<test_type, new_alloc_type>());
316 test_container(list<test_type, so_alloc_type>());
319 test_container(list<test_type, bit_alloc_type>());
322 test_container(list<test_type, po_alloc_type>());
326 test_container(map<test_type, test_type, compare_type, malloc_alloc_type>());
329 test_container(map<test_type, test_type, compare_type, new_alloc_type>());
332 test_container(map<test_type, test_type, compare_type, so_alloc_type>());
335 test_container(map<test_type, test_type, compare_type, bit_alloc_type>());
338 test_container(map<test_type, test_type, compare_type, po_alloc_type>());