Skip to content

Instantly share code, notes, and snippets.

@lsem
Created June 28, 2015 12:42
Show Gist options
  • Save lsem/ba76a2d4150abad517bd to your computer and use it in GitHub Desktop.
Save lsem/ba76a2d4150abad517bd to your computer and use it in GitHub Desktop.
shared_ptr vs raw passing to function benchmark. The aim is to find out how much does passing shared_ptr by value cost.
#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();
}
@lsem
Copy link
Author

lsem commented Jun 28, 2015

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%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment