This source file includes following definitions.
- BOOST_AUTO_TEST_SUITE
- BOOST_AUTO_TEST_CASE
- BOOST_AUTO_TEST_CASE
- BOOST_AUTO_TEST_CASE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "stdafx.h"
22
23 #include "core/stats_output.hpp"
24
25 #define BOOST_TEST_MODULE libjmmcg_tests
26 #include <boost/test/included/unit_test.hpp>
27
28 #include "core/intrusive.hpp"
29 #include "core/thread_wrapper.hpp"
30
31 #include "core/ave_deviation_meter.hpp"
32
33 #include <chrono>
34 #include <set>
35
36 using namespace jmmcg;
37 using namespace ppd;
38
39 using lock_t=api_lock_traits<platform_api, heavyweight_threading>;
40 using timed_results_t=ave_deviation_meter<double>;
41
42 struct data final : public intrusive::node_details_itf<lock_t>, public sp_counter_type<typename intrusive::node_details_itf<lock_t>::atomic_ctr_t::value_type, lock_t> {
43 typedef sp_counter_type<intrusive::node_details_itf<lock_t>::atomic_ctr_t::value_type, lock_t> base_t;
44 typedef typename base_t::lock_traits lock_traits;
45 typedef typename base_t::atomic_ctr_t atomic_ctr_t;
46 typedef typename base_t::deleter_t deleter_t;
47
48 const int i;
49
50 explicit data(int j) noexcept(true)
51 : i(j) {}
52 ~data() noexcept(true) {}
53
54 tstring
55 to_string() const noexcept(false) {
56 tostringstream ss;
57 ss<<"i="<<i;
58 return ss.str();
59 }
60 };
61
62 template<unsigned short N, class Cont, template<class> class Ins>
63 struct add_thread final : public wrapper<platform_api, heavyweight_threading> {
64 typedef wrapper<platform_api, heavyweight_threading> base_t;
65 typedef Cont container_type;
66
67 const typename container_type::size_type num_elems;
68
69 std::vector<typename container_type::value_type> colln;
70 Ins<container_type> inserting;
71
72 add_thread(const typename container_type::size_type n, Ins<container_type> const &c) noexcept(true)
73 : base_t(), num_elems(n), inserting(c) {
74 colln.reserve(num_elems);
75 typename container_type::size_type elem=0;
76 std::generate_n(
77 std::back_inserter(colln),
78 num_elems,
79 [&elem, this]() -> typename container_type::value_type {
80
81 return typename container_type::value_type(new typename container_type::value_type::value_type(N*num_elems+(++elem)));
82 }
83 );
84 }
85 ~add_thread() noexcept(true) {
86 this->delete_thread();
87 }
88
89 bool worker_fn(typename base_t::thread_context_t &) override {
90 std::copy_n(colln.begin(), num_elems, inserting);
91 return true;
92 }
93 };
94
95 template<class Cont>
96 struct pop_thread final : public wrapper<platform_api, heavyweight_threading> {
97 typedef wrapper<platform_api, heavyweight_threading> base_t;
98 typedef Cont container_type;
99
100 const typename container_type::size_type num_elems;
101
102 container_type &cont;
103
104 pop_thread(const typename container_type::size_type n, container_type &c) noexcept(true)
105 : base_t(), num_elems(n), cont(c) {
106 }
107 ~pop_thread() noexcept(true) {
108 this->delete_thread();
109 }
110
111 bool worker_fn(typename base_t::thread_context_t &) override {
112 for (typename container_type::size_type i=0; i<num_elems; ++i) {
113 assert(!cont.empty());
114 cont.pop_front();
115 }
116 return true;
117 }
118 };
119
120 BOOST_AUTO_TEST_SUITE(instrusive_parallel_tests)
121
122 BOOST_AUTO_TEST_SUITE(stack)
123
124 typedef intrusive::stack<data, lock_t> container_type;
125
126 BOOST_AUTO_TEST_SUITE(performance, *boost::unit_test::fixture<jmmcg::stats_to_csv::wrapper>(std::string("intrusive_parallel.csv")))
127
128
129
130
131
132
133 BOOST_AUTO_TEST_CASE(push)
134 {
135 #ifdef JMMCG_PERFORMANCE_TESTS
136 const container_type::size_type num_tests=100;
137 #else
138 const container_type::size_type num_tests=1;
139 #endif
140
141 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
142 2.0,
143 num_tests,
144 []() {
145 #ifdef JMMCG_PERFORMANCE_TESTS
146 const container_type::size_type num_items=10000;
147 #else
148 const container_type::size_type num_items=1000;
149 #endif
150 container_type s;
151 std::chrono::high_resolution_clock::time_point t1, t2;
152 {
153
154 add_thread<1, container_type, std::front_insert_iterator> thread1(num_items, std::front_inserter(s));
155 add_thread<2, container_type, std::front_insert_iterator> thread2(num_items, std::front_inserter(s));
156 add_thread<3, container_type, std::front_insert_iterator> thread3(num_items, std::front_inserter(s));
157 add_thread<4, container_type, std::front_insert_iterator> thread4(num_items, std::front_inserter(s));
158 {
159 t1=std::chrono::high_resolution_clock::now();
160 thread1.create_running();
161 thread2.create_running();
162 thread3.create_running();
163 thread4.create_running();
164 do {
165 api_threading_traits<platform_api, heavyweight_threading>::sleep(100);
166 } while (thread1.is_running() || thread2.is_running() || thread3.is_running() || thread4.is_running());
167
168 t2=std::chrono::high_resolution_clock::now();
169 }
170 }
171
172 BOOST_CHECK(!s.empty());
173 BOOST_CHECK_EQUAL(s.size(), 4*num_items);
174 BOOST_CHECK_EQUAL(s.size_n(), 4*num_items);
175
176 for (auto const &iter : s) {
177 BOOST_CHECK_GE(iter->sp_count(), 1);
178 BOOST_CHECK_EQUAL(iter->sp_count(), 3);
179 }
180 {
181 std::set<int> check_list_integrity;
182 std::transform(
183 s.begin(),
184 s.end(),
185 std::inserter(check_list_integrity, check_list_integrity.begin()),
186 [](container_type::value_type const &v) {
187 return v->i;
188 }
189 );
190 BOOST_CHECK_EQUAL(check_list_integrity.size(), 4*num_items);
191 }
192 return timed_results_t::value_type(4*1000000/static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()))/num_items;
193 }
194 ));
195 #ifdef JMMCG_PERFORMANCE_TESTS
196 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
197 BOOST_CHECK(!timed_results.second);
198 #endif
199 }
200
201
202
203
204
205
206 BOOST_AUTO_TEST_CASE(pop)
207 {
208 #ifdef JMMCG_PERFORMANCE_TESTS
209 const container_type::size_type num_tests=100;
210 #else
211 const container_type::size_type num_tests=1;
212 #endif
213
214 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
215 2.0,
216 num_tests,
217 []() {
218 #ifdef JMMCG_PERFORMANCE_TESTS
219 const container_type::size_type num_items=10000;
220 #else
221 const container_type::size_type num_items=1000;
222 #endif
223 container_type s;
224 container_type::size_type elem=0;
225 std::chrono::high_resolution_clock::time_point t1, t2;
226 std::generate_n(
227 std::front_inserter(s),
228 4*num_items,
229 [&elem]() {
230
231 return container_type::value_type(new container_type::value_type::value_type(++elem));
232 }
233 );
234 {
235
236 pop_thread<container_type> thread1(num_items, s);
237 pop_thread<container_type> thread2(num_items, s);
238 pop_thread<container_type> thread3(num_items, s);
239 pop_thread<container_type> thread4(num_items, s);
240 {
241 t1=std::chrono::high_resolution_clock::now();
242 thread1.create_running();
243 thread2.create_running();
244 thread3.create_running();
245 thread4.create_running();
246 do {
247 api_threading_traits<platform_api, heavyweight_threading>::sleep(100);
248 } while (thread1.is_running() || thread2.is_running() || thread3.is_running() || thread4.is_running());
249
250 t2=std::chrono::high_resolution_clock::now();
251 }
252 }
253
254 BOOST_CHECK(s.empty());
255 BOOST_CHECK_EQUAL(s.size(), container_type::size_type());
256 BOOST_CHECK_EQUAL(s.size_n(), container_type::size_type());
257 return timed_results_t::value_type(4*1000000/static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()))/num_items;
258 }
259 ));
260 #ifdef JMMCG_PERFORMANCE_TESTS
261 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
262 BOOST_CHECK(!timed_results.second);
263 #endif
264 }
265
266 BOOST_AUTO_TEST_SUITE_END()
267
268 BOOST_AUTO_TEST_SUITE(slist)
269
270 typedef intrusive::slist<data, lock_t> container_type;
271
272
273
274
275
276
277 BOOST_AUTO_TEST_CASE(push_front)
278 {
279 #ifdef JMMCG_PERFORMANCE_TESTS
280 const container_type::size_type num_tests=100;
281 #else
282 const container_type::size_type num_tests=1;
283 #endif
284
285 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
286 2.0,
287 num_tests,
288 []() {
289 #ifdef JMMCG_PERFORMANCE_TESTS
290 const container_type::size_type num_items=10000;
291 #else
292 const container_type::size_type num_items=1000;
293 #endif
294 container_type s;
295 std::chrono::high_resolution_clock::time_point t1, t2;
296 {
297
298 add_thread<1, container_type, std::front_insert_iterator> thread1(num_items, std::front_inserter(s));
299 add_thread<2, container_type, std::front_insert_iterator> thread2(num_items, std::front_inserter(s));
300 add_thread<3, container_type, std::front_insert_iterator> thread3(num_items, std::front_inserter(s));
301 add_thread<4, container_type, std::front_insert_iterator> thread4(num_items, std::front_inserter(s));
302 {
303 t1=std::chrono::high_resolution_clock::now();
304 thread1.create_running();
305 thread2.create_running();
306 thread3.create_running();
307 thread4.create_running();
308 do {
309 api_threading_traits<platform_api, heavyweight_threading>::sleep(100);
310 } while (thread1.is_running() || thread2.is_running() || thread3.is_running() || thread4.is_running());
311
312 t2=std::chrono::high_resolution_clock::now();
313 }
314 }
315
316 BOOST_CHECK(!s.empty());
317 BOOST_CHECK_EQUAL(s.size(), 4*num_items);
318 BOOST_CHECK_EQUAL(s.size_n(), 4*num_items);
319
320 for (auto const &iter : s) {
321 BOOST_CHECK_GE(iter->sp_count(), 1);
322 BOOST_CHECK_EQUAL(iter->sp_count(), 3);
323 }
324 {
325 std::set<int> check_list_integrity;
326 std::transform(
327 s.begin(),
328 s.end(),
329 std::inserter(check_list_integrity, check_list_integrity.begin()),
330 [](container_type::value_type const &v) {
331 return v->i;
332 }
333 );
334 BOOST_CHECK_EQUAL(check_list_integrity.size(), 4*num_items);
335 }
336 BOOST_CHECK(s.penultimate_reachable_from_prefront());
337 return timed_results_t::value_type(4*1000000/static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()))/num_items;
338 }
339 ));
340 #ifdef JMMCG_PERFORMANCE_TESTS
341 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
342 BOOST_CHECK(!timed_results.second);
343 #endif
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 BOOST_AUTO_TEST_CASE(pop_front)
397 {
398 #ifdef JMMCG_PERFORMANCE_TESTS
399 const container_type::size_type num_tests=100;
400 #else
401 const container_type::size_type num_tests=1;
402 #endif
403
404 const std::pair<timed_results_t, bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
405 2.0,
406 num_tests,
407 []() {
408 #ifdef JMMCG_PERFORMANCE_TESTS
409 const container_type::size_type num_items=10000;
410 #else
411 const container_type::size_type num_items=1000;
412 #endif
413 container_type s;
414 container_type::size_type elem=0;
415 std::chrono::high_resolution_clock::time_point t1, t2;
416 std::generate_n(
417 std::front_inserter(s),
418 4*num_items,
419 [&elem]() -> container_type::value_type {
420
421 return container_type::value_type(new container_type::value_type::value_type(++elem));
422 }
423 );
424 {
425
426 pop_thread<container_type> thread1(num_items, s);
427 pop_thread<container_type> thread2(num_items, s);
428 pop_thread<container_type> thread3(num_items, s);
429 pop_thread<container_type> thread4(num_items, s);
430 {
431 t1=std::chrono::high_resolution_clock::now();
432 thread1.create_running();
433 thread2.create_running();
434 thread3.create_running();
435 thread4.create_running();
436 do {
437 api_threading_traits<platform_api, heavyweight_threading>::sleep(100);
438 } while (thread1.is_running() || thread2.is_running() || thread3.is_running() || thread4.is_running());
439
440 t2=std::chrono::high_resolution_clock::now();
441 }
442 }
443
444 BOOST_CHECK(s.empty());
445 BOOST_CHECK_EQUAL(s.size(), container_type::size_type());
446 BOOST_CHECK_EQUAL(s.size_n(), container_type::size_type());
447 return timed_results_t::value_type(4*1000000/static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()))/num_items;
448 }
449 ));
450 #ifdef JMMCG_PERFORMANCE_TESTS
451 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
452 BOOST_CHECK(!timed_results.second);
453 #endif
454 }
455
456 BOOST_AUTO_TEST_SUITE_END()
457
458 BOOST_AUTO_TEST_SUITE_END()
459
460 BOOST_AUTO_TEST_SUITE_END()