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 queue.insert(queue.end(), value);
133 if (queue.size() == 1) pthread_cond_signal(&condition);
136 template<typename Container>
138 Queue<Container>::swap(Container& container)
140 AutoLock auto_lock(lock);
141 while (queue.empty()) pthread_cond_wait(&condition, &lock);
142 queue.swap(container);
147 // NB: Make this the last data member of an object defining operator()().
152 Attributes(int state = PTHREAD_CREATE_JOINABLE);
153 ~Attributes() {pthread_attr_destroy(&attributes);}
156 inline pthread_attr_t* operator&() {return &attributes;}
159 pthread_attr_t attributes;
163 Thread() {thread = pthread_self();}
167 template <typename ThreadOwner>
168 void create(ThreadOwner* owner);
174 Thread::Attributes::Attributes(int state)
176 pthread_attr_init(&attributes);
177 pthread_attr_setdetachstate(&attributes, state);
182 if (!pthread_equal(thread, pthread_self()))
183 pthread_join(thread, 0);
186 template<typename ThreadOwner>
188 create_thread(void* _this)
190 ThreadOwner* owner = static_cast<ThreadOwner*>(_this);
195 template<typename ThreadOwner>
197 Thread::create(ThreadOwner* owner)
199 Thread::Attributes attributes;
200 pthread_create(&thread, &attributes, create_thread<ThreadOwner>, owner);
203 template<typename Container>
207 Consumer(Queue<Container>& _queue)
209 {thread.create(this);}
215 Queue<Container>& queue;
219 template<typename Container>
221 Consumer<Container>::operator()()
223 for (int j = insert_values * iterations; j > 0;)
226 queue.swap(container);
227 j -= container.size();
231 template<typename TestType>
232 struct Value : public pair<TestType, TestType>
235 : pair<TestType, TestType>(0, 0)
238 inline Value operator++() {return ++this->first, *this;}
239 inline operator TestType() const {return this->first;}
242 template<typename Container>
243 class ProducerConsumer : private Queue<Container>
246 ProducerConsumer() {thread.create(this);}
255 template<typename Container>
257 ProducerConsumer<Container>::operator()()
259 Consumer<Container> consumer(*this);
260 Value<test_type> test_value;
261 for (int j = insert_values * iterations; j-- > 0;)
262 this->push_back(++test_value);
265 template<typename Container>
267 test_container(Container obj)
269 using namespace __gnu_test;
273 resource_counter resource;
275 clear_counters(time, resource);
276 start_counters(time, resource);
278 ProducerConsumer<Container> pc1;
279 ProducerConsumer<Container> pc2;
281 stop_counters(time, resource);
283 std::ostringstream comment;
284 comment << "iterations: " << iterations << '\t';
285 comment << "type: " << __cxa_demangle(typeid(obj).name(), 0, 0, &status);
286 report_header(__FILE__, comment.str());
287 report_performance(__FILE__, string(), time, resource);
293 test_container(vector<test_type, malloc_alloc_type>());
296 test_container(vector<test_type, new_alloc_type>());
299 test_container(vector<test_type, so_alloc_type>());
302 test_container(vector<test_type, bit_alloc_type>());
305 test_container(vector<test_type, po_alloc_type>());
309 test_container(list<test_type, malloc_alloc_type>());
312 test_container(list<test_type, new_alloc_type>());
315 test_container(list<test_type, so_alloc_type>());
318 test_container(list<test_type, bit_alloc_type>());
321 test_container(list<test_type, po_alloc_type>());
325 test_container(map<test_type, test_type, compare_type, malloc_alloc_type>());
328 test_container(map<test_type, test_type, compare_type, new_alloc_type>());
331 test_container(map<test_type, test_type, compare_type, so_alloc_type>());
334 test_container(map<test_type, test_type, compare_type, bit_alloc_type>());
337 test_container(map<test_type, test_type, compare_type, po_alloc_type>());