18 #include <unordered_map>
20 #include "cmdline.hpp"
22 #include "microtime.hpp"
25 #include "container.hpp"
31 #ifdef USE_MALLOC_COUNT
32 #include "malloc_count.h"
47 std::cout << s << std::endl;
64 static const unsigned RNGMOD = ((1ULL << 32) - 5);
65 static const unsigned RNGMUL = 69070U;
70 state = (unsigned)((RNGMUL * (
unsigned long long)state) % RNGMOD);
88 bytes_1(
char c) : data(c) { }
90 data = (char) (i % 256);
95 char get_char()
const {
98 bool operator==(
const bytes_1 other) {
99 return data == other.data;
101 operator unsigned char()
const {
119 char get_char()
const {
120 return (
char) (data % 256);
122 bool operator==(
const bytes_8 other) {
123 return data == other.data;
132 for (
int k = 0; k < 8; k++)
133 data[k] = (int64_t)c;
136 for (
int k = 0; k < 8; k++)
142 char get_char()
const {
143 return (
char) (data[0] % 256);
145 bool operator==(
const bytes_64 other) {
146 return data == other.data;
152 template <
class Datastruct>
154 size_t sz = d.size();
155 for (
size_t i = 0; i < sz; i++)
156 std::swap(d[i], d[rand() % sz]);
163 template <
class Datastruct>
166 size_t nb_total = (size_t) cmdline::parse_or_default_int64(
"n", 100000000);
167 size_t repeat = (size_t) cmdline::parse_or_default_int64(
"r", 1000);
168 size_t block = nb_total / repeat;
170 printf(
"length %lld\n",block);
171 uint64_t start_time = microtime::now();
175 for (
size_t j = 0; j < repeat; j++) {
176 for (
size_t i = 0; i < block; i++) {
180 for (
size_t i = 0; i < block; i++) {
181 res += d.pop_front().get();
183 size_t v = d.pop_front().get();
187 exec_time = microtime::seconds_since(start_time);
196 template <
class Datastruct,
bool SkipPop>
199 size_t nb_total = (size_t) cmdline::parse_or_default_int64(
"n", 100000000);
200 size_t repeat = (size_t) cmdline::parse_or_default_int64(
"r", 1000);
201 size_t block = nb_total / repeat;
203 printf(
"length %lld\n",block);
204 uint64_t start_time = microtime::now();
207 for (
size_t j = 0; j < repeat; j++) {
208 for (
size_t i = 0; i < block; i++) {
212 #ifdef FIFO_LIFO_ONLY_COUNT_POP
213 start_time = microtime::now();
216 for (
size_t i = 0; i < block; i++) {
217 res += d.pop_back().get();
223 exec_time = microtime::seconds_since(start_time);
227 template <
class Datastruct>
229 return scenario_lifo_with_or_without_pop<Datastruct, false>();
232 template <
class Datastruct>
234 return scenario_lifo_with_or_without_pop<Datastruct, true>();
237 template <
class Datastruct>
240 size_t nb_total = (size_t) cmdline::parse_or_default_int64(
"n", 100000000);
241 size_t repeat = (size_t) cmdline::parse_or_default_int64(
"r", 1000);
242 size_t block = nb_total / repeat;
244 printf(
"length %lld\n",block);
245 uint64_t start_time = microtime::now();
248 for (
size_t j = 0; j < repeat; j++) {
249 for (
size_t i = 0; i < block; i++) {
253 #ifdef FIFO_LIFO_ONLY_COUNT_POP
254 start_time = microtime::now();
256 for (
size_t i = 0; i < block; i++) {
257 res += d.pop_front().get();
260 exec_time = microtime::seconds_since(start_time);
266 template <
class Datastruct,
bool should_push,
bool should_pop>
269 typedef typename Datastruct::size_type size_type;
271 size_t nb_total = n / p;
272 printf(
"length %lld\n",nb_total);
275 for (size_type i = 0; i < p; i++) {
276 for (size_type j = 0; j < nb_total; j++)
279 uint64_t start_time = microtime::now();
280 for (size_type k = 0; k < r; k++) {
281 size_type b1 = rand() % p;
282 size_type b2 = rand() % (p-1);
286 ds[b1].concat(ds[b2]);
288 size_type b3 = rand() % (p-1);
292 Datastruct& src = ds[b3];
293 if (src.size() > 1) {
294 size_t posn = src.size() / 2;
295 src.split(posn, ds[b2]);
298 for (
size_t i = 0; i < h; i++)
299 src.push_back(value_type(i));
301 for (
size_t i = 0; i < h; i++)
302 res += (size_type)src.pop_front().get();
304 exec_time = microtime::seconds_since(start_time);
306 for (
int i = 0; i < p; i++)
310 template <
class Datastruct>
313 typedef typename Datastruct::size_type size_type;
314 size_t n = (size_t) cmdline::parse_or_default_int64(
"n", 100000000);
315 size_t p = (size_t) cmdline::parse_or_default_int64(
"p", std::max(n/100, (size_type)2));
316 size_t r = (size_t) cmdline::parse_or_default_int64(
"r", 100000);
317 size_t h = (size_t) cmdline::parse_or_default_int64(
"h", 0);
318 bool should_push = cmdline::parse_or_default_bool(
"should_push",
true);
319 bool should_pop = cmdline::parse_or_default_bool(
"should_pop",
false);
322 Datastruct* ds =
new Datastruct[p];
323 if (should_push && should_pop)
324 _scenario_split_merge<Datastruct,true,true>(ds, n, p, r, h);
325 else if (! should_push && should_pop)
326 _scenario_split_merge<Datastruct,false,true>(ds, n, p, r, h);
327 else if (should_push && ! should_pop)
328 _scenario_split_merge<Datastruct,true,false>(ds, n, p, r, h);
330 _scenario_split_merge<Datastruct,false,false>(ds, n, p, r, h);
335 template <
class Datastruct,
class Filter>
336 void filter(Datastruct& dst, Datastruct& src,
const Filter& filt,
int cutoff) {
338 if (src.size() <= cutoff) {
339 while (! src.empty()) {
340 value_type item = src.pop_back();
347 size_t mid = src.size() / 2;
348 src.split(mid, src2);
349 filter(dst, src, filt, cutoff);
350 filter(dst2, src2, filt, cutoff);
355 template <
class Datastruct>
357 typedef typename Datastruct::size_type size_type;
359 size_t cutoff = cmdline::parse_or_default_int64(
"cutoff", 8096);
360 size_t n = cmdline::parse_or_default_int64(
"n", 100000000);
361 size_t r = (size_t) cmdline::parse_or_default_int64(
"r", 1);
362 size_t nb_total = n / r;
363 printf(
"length %lld\n",nb_total);
364 const size_t m = 1<<30;
368 for (
size_t i = 0; i < nb_total; i++)
369 src.push_back(value_type(i));
370 auto filt = [] (value_type v) {
371 return (v.get() % m) != 0;
373 uint64_t start_time = microtime::now();
374 for (
size_t i = 0; i < r; i++) {
375 filter(dst, src, filt, cutoff);
378 exec_time = microtime::seconds_since(start_time);
379 res = src.size() + dst.size();
389 #define PAYLOAD 16 // Size of the object
391 template <
class Map,
class Obj>
393 using map_type = Map;
394 using key_type =
typename map_type::key_type;
395 using obj_type = Obj;
396 using mapped_type =
typename map_type::mapped_type;
398 size_t n = cmdline::parse_or_default_uint64(
"n", 1000000);
399 bool test_random = cmdline::parse_or_default_bool(
"test_random",
true);
400 key_type* INSERT =
new key_type[n];
401 key_type* SEARCH =
new key_type[n];
402 obj_type* OBJ =
new obj_type[n];
405 for(
long i=0;i<n;++i) {
406 INSERT[i] = 0x80000000 + i * 2;
407 SEARCH[i] = 0x80000000 + i * 2;
413 std::random_shuffle(INSERT, INSERT + n);
414 std::random_shuffle(SEARCH, SEARCH + n);
417 auto init = [=] (map_type& bag) {
418 for(
size_t i=0;i<n;++i) {
420 key_type key = INSERT[i];
421 auto element = &OBJ[i];
422 element->value = key;
429 cmdline::argmap_dispatch c;
430 c.add(
"insert", [=] {
432 uint64_t start_time = microtime::now();
434 exec_time = microtime::seconds_since(start_time);
437 c.add(
"change", [=] {
440 uint64_t start_time = microtime::now();
442 for(
size_t i=0;i<n;++i) {
444 unsigned key = SEARCH[i];
445 auto j = bag.find(key);
450 auto element = (*j).second;
456 element->value = key;
459 exec_time = microtime::seconds_since(start_time);
465 uint64_t start_time = microtime::now();
466 for(
size_t i=0;i<n;++i) {
469 auto key = SEARCH[i];
470 auto j = bag.find(key);
477 auto element = (*j).second;
478 if (element->value != key)
481 exec_time = microtime::seconds_since(start_time);
487 uint64_t start_time = microtime::now();
488 for(
size_t i=0;i<n;++i) {
490 key_type key = SEARCH[i]+1;
491 auto j = bag.find(key);
495 exec_time = microtime::seconds_since(start_time);
498 c.add(
"remove", [=] {
501 uint64_t start_time = microtime::now();
502 for(
size_t i=0;i<n;++i) {
504 auto key = SEARCH[i];
505 auto j = bag.find(key);
513 auto element = (*j).second;
517 exec_time = microtime::seconds_since(start_time);
521 return c.find_by_arg(
"map_benchmark");
528 template <
class Sequence>
530 cmdline::argmap_dispatch c;
531 c.add(
"test", scenario_test<Sequence>());
532 c.add(
"fifo", scenario_fifo<Sequence>());
533 c.add(
"lifo", scenario_lifo<Sequence>());
534 c.add(
"fill_back", scenario_fill_back<Sequence>());
535 c.add(
"split_merge", scenario_split_merge<Sequence>());
536 c.add(
"filter", scenario_filter<Sequence>());
537 cmdline::dispatch_by_argmap(c,
"scenario");
548 int Chunk_capacity=512,
551 class Item_alloc=std::allocator<Item> >
class SeqStruct,
553 template<class Chunk_item, int Cap, class Item_alloc2=std::allocator<Item>>
class Chunk_struct>
556 static constexpr
int default_chunksize = 512;
557 util::cmdline::argmap_dispatch c;
558 c.add(
"512", [] { dispatch_by_scenario<SeqStruct<Item,512,Cache,Chunk_struct> >(); });
559 #ifndef SKIP_CHUNKSIZE
560 c.add(
"64", [] { dispatch_by_scenario<SeqStruct<Item,64,Cache,Chunk_struct> >(); });
561 c.add(
"128", [] { dispatch_by_scenario<SeqStruct<Item,128,Cache,Chunk_struct> >(); });
562 c.add(
"256", [] { dispatch_by_scenario<SeqStruct<Item,256,Cache,Chunk_struct> >(); });
563 c.add(
"1024", [] { dispatch_by_scenario<SeqStruct<Item,1024,Cache,Chunk_struct> >(); });
564 c.add(
"2048", [] { dispatch_by_scenario<SeqStruct<Item,2048,Cache,Chunk_struct> >(); });
565 c.add(
"4096", [] { dispatch_by_scenario<SeqStruct<Item,4096,Cache,Chunk_struct> >(); });
566 c.add(
"8192", [] { dispatch_by_scenario<SeqStruct<Item,8192,Cache,Chunk_struct> >(); });
568 util::cmdline::dispatch_by_argmap(c,
"chunk_size", std::to_string(default_chunksize));
572 template <
class Item,
573 int Chunk_capacity=512,
576 class Item_alloc=std::allocator<Item> >
577 using mystack = chunkedseq::bootstrapped::stack<Item, Chunk_capacity, Cache>;
579 template <
class Item,
580 int Chunk_capacity=512,
583 class Item_alloc=std::allocator<Item> >
584 using mybag = chunkedseq::bootstrapped::bagopt<Item, Chunk_capacity, Cache>;
587 template <
class Item,
588 int Chunk_capacity=512,
591 class Item_alloc=std::allocator<Item> >
592 using myfftreestack = chunkedseq::ftree::stack<Item, Chunk_capacity, Cache>;
594 template <
class Item,
595 int Chunk_capacity=512,
598 class Item_alloc=std::allocator<Item> >
599 using myfftreebag = chunkedseq::ftree::bagopt<Item, Chunk_capacity, Cache>;
601 template <
class Item>
603 util::cmdline::argmap_dispatch c;
605 c.add(
"stl_deque", [] {
606 using seq_type = pasl::data::stl::deque_seq<Item>;
607 dispatch_by_scenario<seq_type>();
612 c.add(
"stl_rope", [] {
613 using seq_type = pasl::data::stl::rope_seq<Item>;
614 dispatch_by_scenario<seq_type>();
618 #ifndef SKIP_CHUNKEDSEQ
619 c.add(
"chunkedseq", [] {
620 dispatch_for_chunkedseq<chunkedseq::bootstrapped::deque, Item, data::fixedcapacity::heap_allocated::ringbuffer_ptr>();
623 #ifndef SKIP_CHUNKEDSEQ_OPT
624 c.add(
"chunkedseq_stack", [] {
625 dispatch_for_chunkedseq<mystack, Item, data::fixedcapacity::heap_allocated::stack>();
627 c.add(
"chunkedseq_bag", [] {
628 dispatch_for_chunkedseq<mybag, Item, data::fixedcapacity::heap_allocated::stack>();
633 c.add(
"chunkedftree", [] {
634 dispatch_for_chunkedseq<chunkedseq::ftree::deque, Item, data::fixedcapacity::heap_allocated::ringbuffer_ptr>();
637 #ifndef SKIP_FTREE_OPT
638 c.add(
"chunkedftree_stack", [] {
639 dispatch_for_chunkedseq<myfftreestack, Item, data::fixedcapacity::heap_allocated::stack>();
641 c.add(
"chunkedftree_bag", [] {
642 dispatch_for_chunkedseq<myfftreebag, Item, data::fixedcapacity::heap_allocated::stack>();
645 util::cmdline::dispatch_by_argmap(c,
"sequence");
652 static constexpr
int default_itemsize = 8;
653 util::cmdline::argmap_dispatch c;
654 c.add(
"8", [] { dispatch_by_sequence<bytes_8>(); });
655 #ifndef SKIP_ITEMSIZE
656 c.add(
"1", [] { dispatch_by_sequence<bytes_1>(); });
657 c.add(
"64", [] { dispatch_by_sequence<bytes_64>(); });
659 util::cmdline::dispatch_by_argmap(c,
"itemsize", std::to_string(default_itemsize));
667 cmdline::argmap_dispatch c;
668 using key_type = long;
669 using obj_type =
struct {
674 using stl_map_type = std::map<key_type, value_type>;
676 using unordered_map_type = std::unordered_map<key_type, value_type>;
677 c.add(
"stl_map", scenario_map<stl_map_type,obj_type>());
678 c.add(
"chunkedseq_map", scenario_map<chunkedseq_map_type,obj_type>());
679 c.add(
"stl_unordered_set", scenario_map<unordered_map_type,obj_type>());
680 cmdline::dispatch_by_argmap(c,
"map");
692 cmdline::argmap_dispatch c;
695 cmdline::dispatch_by_argmap(c,
"mode",
"sequence");
698 int main(
int argc,
char** argv) {
699 pasl::util::cmdline::set(argc, argv);
706 printf(
"result %lld\n", (
long long)
res);
708 #ifdef USE_MALLOC_COUNT
709 malloc_pasl_report();
thunk_t scenario_filter()
base::ringbuffer_ptr< base::heap_allocator< Item, Capacity+1 >> ringbuffer_ptr
STL-style map data structure.
void dispatch_by_sequence()
void dispatch_by_benchmark_mode()
chunkedseq::bootstrapped::bagopt< Item, Chunk_capacity, Cache > mybag
Definitions of a few cached-measurement policies.
chunkedseq::ftree::bagopt< Item, Chunk_capacity, Cache > myfftreebag
chunkedseq::bootstrapped::stack< Item, Chunk_capacity, Cache > mystack
void failwith(std::string s)
void shuffle(Datastruct &d)
thunk_t scenario_split_merge()
void dispatch_by_scenario()
void dispatch_by_itemsize()
thunk_t scenario_lifo_with_or_without_pop()
void _scenario_split_merge(Datastruct *ds, size_t n, size_t p, size_t r, size_t h)
void dispatch_for_chunkedseq()
std::function< void()> thunk_t
thunk_t scenario_fill_back()
int main(int argc, char **argv)
void filter(Datastruct &dst, Datastruct &src, const Filter &filt, int cutoff)
void mysrand(unsigned seed)
chunkedseq::ftree::stack< Item, Chunk_capacity, Cache > myfftreestack
Chunked-sequence functor.