static double destruction(std::size_t N) { std::size_t count = 1; std::size_t elapsed = 0; s_indices.resize(N); std::generate(s_indices.begin(), s_indices.end(), IncrementFill()); for (; elapsed < g_limit; ++count) { std::shuffle(s_indices.begin(), s_indices.end(), s_rng); { Subject subject; std::vector<Foo> foo(N); for (auto index : s_indices) { Foo::connect_method(subject, foo[index]); } s_timer.reset(); // Destruction } elapsed += s_timer.count<Timer_u>(); } return _calculate_score(N, g_limit, count); }
void bs2_benchmark() { Rng_t rng; Eng_t eng (0, 100); chrono_timer timer; boost::signals2::signal<void(Rng_t&)> signal_one; boost::signals2::signal<void(std::size_t, Rng_t&)> signal_two; // N = 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 for (std::size_t N = 16; N <= 128; N *= 2) // magic numbers are globals { Width_t sum_previous = 1; Width_t sum_current = 2; Width_t sum_count = 0; // loop until wrap around occurs or until max count is reached while (sum_previous < sum_current && sum_count < 100) { // try to randomize access patterns std::vector<std::size_t> random_index(N); std::generate(random_index.begin(), random_index.end(), IncrementFill()); std::shuffle(random_index.begin(), random_index.end(), rng); // delay seems to increase timing accuracy sum_previous = sum_current; timer.delay(10); timer.reset(); { // time boost::signals2::trackable construction overhead std::vector<Bs2> obj(N); for (std::size_t index : random_index) { // what is the next operation? connect or emit if (eng(rng) > 50) { Bs2* ptr = &obj[index]; signal_one.connect(boost::bind(&Bs2::method_one, ptr, _1)); signal_two.connect(boost::bind(&Bs2::method_two, ptr, _1, _2)); } else { signal_one(rng); signal_two(index, rng); } } } sum_current += timer.elapsed_us(); ++sum_count; } // calculate milliseconds and output the relative performance double elapsed_ms = (sum_previous / (double)sum_count) * 0.001; std::cout << (N / elapsed_ms) << std::endl; } std::cout << Bs2::s_sum << std::endl; }