|
|
|
#include <memory> |
|
#include <cassert> |
|
#include <cstdio> |
|
#include <chrono> |
|
#include <algorithm> |
|
#include <cstdlib> |
|
#include <functional> |
|
|
|
int increment_value; |
|
|
|
#ifdef __clang__ |
|
#define NO_INLINED(F) __declspec(noinline) F |
|
#else |
|
#error "Compiiled not supported: write proper noinline declspec" |
|
#endif |
|
|
|
NO_INLINED(int counter_fn(std::shared_ptr<int> counter)) |
|
{ |
|
return *counter + increment_value; |
|
} |
|
|
|
NO_INLINED(int counter_fn_ref(const std::shared_ptr<int> & counter)) |
|
{ |
|
return *counter + increment_value; |
|
} |
|
|
|
NO_INLINED(int counter_fn(int *counter)) |
|
{ |
|
return *counter + increment_value; |
|
} |
|
|
|
|
|
int do_copy_shared_ptr_test(int iterations_count, int round_size=1000) |
|
{ |
|
std::shared_ptr<int> counter = std::make_shared<int>(); |
|
*counter = 0; |
|
|
|
for (unsigned i = 0; i != iterations_count; ++i) |
|
{ |
|
for (unsigned j = 0; j != round_size; ++j) |
|
{ |
|
auto result = counter_fn(counter); |
|
*counter = result; |
|
} |
|
} |
|
|
|
return *counter; |
|
} |
|
|
|
int do_copy_shared_ptr_ref_test(int iterations_count, int round_size=1000) |
|
{ |
|
std::shared_ptr<int> counter = std::make_shared<int>(); |
|
*counter = 0; |
|
|
|
for (unsigned i = 0; i != iterations_count; ++i) |
|
{ |
|
for (unsigned j = 0; j != round_size; ++j) |
|
{ |
|
auto result = counter_fn_ref(counter); |
|
*counter = result; |
|
} |
|
} |
|
|
|
return *counter; |
|
} |
|
|
|
|
|
int do_copy_raw_ptr_test(int iterations_count, int round_size=1000) |
|
{ |
|
int *counter = new int(); |
|
*counter = 0; |
|
|
|
for (unsigned i = 0; i != iterations_count; ++i) |
|
{ |
|
for (unsigned j = 0; j != round_size; ++j) |
|
{ |
|
auto result = counter_fn(counter); |
|
*counter = result; |
|
} |
|
} |
|
|
|
return *counter; |
|
} |
|
|
|
|
|
|
|
unsigned microseconds_timer(std::function<void()> cb) |
|
{ |
|
const auto start = std::chrono::high_resolution_clock::now(); |
|
cb(); |
|
const auto duration = std::chrono::high_resolution_clock::now() - start; |
|
return std::chrono::duration_cast<std::chrono::microseconds>(duration).count(); |
|
} |
|
|
|
void compare_results(const char *a_name, const char *b_name, unsigned a_val, unsigned b_val) |
|
{ |
|
std::printf("'%s' is bettern then '%s' by %d%%\n", |
|
(a_val < b_val ? a_name : b_name), |
|
(a_val < b_val ? b_name : a_name), |
|
100 - (int)(std::min(a_val, b_val) / (double) std::max(a_val, b_val) * 100)); |
|
} |
|
|
|
void do_test() |
|
{ |
|
int rounds = 10000; |
|
int block = 10000; |
|
|
|
int raw_result, sharedptr_result, shared_ptrref_result; |
|
|
|
const unsigned shared_time_ms = microseconds_timer([&]{ |
|
sharedptr_result = do_copy_shared_ptr_test(rounds, block); |
|
}); |
|
const unsigned raw_time_ms = microseconds_timer([&]{ |
|
raw_result = do_copy_raw_ptr_test(rounds, block); |
|
}); |
|
|
|
const unsigned shared_ptr_ref_ms = microseconds_timer([&]{ |
|
shared_ptrref_result = do_copy_shared_ptr_ref_test(rounds, block); |
|
}); |
|
|
|
assert(sharedptr_result == raw_result && shared_ptrref_result == raw_result); |
|
|
|
std::printf("shared time: %d\n", shared_time_ms); |
|
std::printf("shared by reference time: %d\n", shared_ptr_ref_ms); |
|
std::printf("raw time: %d\n", raw_time_ms); |
|
|
|
compare_results("raw", "shared", raw_time_ms, shared_time_ms); |
|
compare_results("raw", "shared by reference", raw_time_ms, shared_ptr_ref_ms); |
|
compare_results("shared", "shared by reference", shared_time_ms, shared_ptr_ref_ms); |
|
} |
|
|
|
int main(int argc, char *argv[]) |
|
{ |
|
assert(argc == 2); |
|
increment_value = std::atoi(argv[1]); |
|
do_test(); |
|
} |
|
|
|
|
Possible output:
clang++ -O3 -o sharedptr_benchmark -std=c++14 -stdlib=libc++ shared_ptr_benchmark.cpp
./sharedptr_benchmark 24
shared time: 1987447
shared by reference time: 229100
raw time: 251228
'raw' is better then 'shared' by 88%
'shared by reference' is better then 'raw' by 9%
'shared by reference' is better then 'shared' by 89%