Skip to content

Commit 35378d6

Browse files
committed
Updated speed benchmark to output markdown
1 parent a88f0b2 commit 35378d6

File tree

1 file changed

+94
-6
lines changed

1 file changed

+94
-6
lines changed

tests/speed_benchmark.cpp

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include "speed_benchmark_common.hpp"
22

3+
#include <algorithm>
34
#include <cmath>
5+
#include <iomanip>
6+
#include <unordered_map>
7+
#include <vector>
48

59
template<typename B, typename F>
610
auto run_benchmark_for(F&& func) {
@@ -10,8 +14,9 @@ auto run_benchmark_for(F&& func) {
1014
double elapsed_square = 0.0;
1115
double attempts = 0.0;
1216
constexpr std::size_t num_iter = 1'000'000;
17+
constexpr double min_time = 0.2;
1318

14-
while (elapsed * num_iter < 1.0) {
19+
while (elapsed * num_iter < min_time) {
1520
auto prev = timer::now();
1621

1722
for (std::size_t i = 0; i < num_iter; ++i) {
@@ -50,6 +55,54 @@ auto run_benchmark(F&& func) {
5055
return std::make_pair(result, std::make_pair(ratio, ratio_stddev));
5156
}
5257

58+
std::unordered_map<std::string, std::unordered_map<std::string, std::vector<double>>> results;
59+
60+
template<typename T>
61+
struct get_type_name;
62+
63+
template<typename T>
64+
struct get_type_name<std::shared_ptr<T>> {
65+
static constexpr const char* value = "weak/shared";
66+
};
67+
68+
template<typename T>
69+
struct get_type_name<oup::observable_unique_ptr<T>> {
70+
static constexpr const char* value = "observer/obs_unique";
71+
};
72+
73+
template<typename T>
74+
struct get_type_name<oup::observable_sealed_ptr<T>> {
75+
static constexpr const char* value = "observer/obs_sealed";
76+
};
77+
78+
template<typename T, typename R>
79+
void do_report(const char* name, const R& which) {
80+
std::cout << " - " << name << ": " << which.first.first * 1e6 << " +/- "
81+
<< which.first.second * 1e6 << "us "
82+
<< "(x" << which.second.first << " +/- " << which.second.second << ")" << std::endl;
83+
84+
results[name][get_type_name<T>::value].push_back(which.second.first);
85+
}
86+
87+
double median(std::vector<double> v) {
88+
const auto n = v.size() / 2;
89+
std::nth_element(v.begin(), v.begin() + n, v.end());
90+
return *(v.begin() + n);
91+
}
92+
93+
std::string round1(double v) {
94+
std::ostringstream str;
95+
str << std::fixed << std::setprecision(1);
96+
str << std::round(v * 10.0) / 10.0;
97+
98+
auto res = str.str();
99+
if (res.find_first_of('.') == std::string::npos) {
100+
res += ".0";
101+
}
102+
103+
return res;
104+
}
105+
53106
template<typename T>
54107
void do_benchmarks_for_ptr(const char* type_name, const char* ptr_name) {
55108
using B = benchmark<T>;
@@ -70,11 +123,8 @@ void do_benchmarks_for_ptr(const char* type_name, const char* ptr_name) {
70123
auto dereference_weak = run_benchmark<B>([](auto& b) { return b.dereference_weak(); });
71124

72125
std::cout << ptr_name << "<" << type_name << ">:" << std::endl;
73-
#define report(which) \
74-
std::cout << " - " << #which << ": " << which.first.first * 1e6 << " +/- " \
75-
<< which.first.second * 1e6 << "us " \
76-
<< "(x" << which.second.first << " +/- " << which.second.second << ")" << std::endl
77126

127+
#define report(which) do_report<T>(#which, which)
78128
report(construct_destruct_owner_empty);
79129
report(construct_destruct_owner);
80130
report(construct_destruct_owner_factory);
@@ -83,8 +133,8 @@ void do_benchmarks_for_ptr(const char* type_name, const char* ptr_name) {
83133
report(construct_destruct_weak);
84134
report(construct_destruct_weak_copy);
85135
report(dereference_weak);
86-
87136
#undef report
137+
88138
std::cout << std::endl;
89139
}
90140

@@ -100,5 +150,43 @@ int main() {
100150
do_benchmarks<float>("float");
101151
do_benchmarks<std::string>("string");
102152
do_benchmarks<std::array<int, 65'536>>("big_array");
153+
154+
std::vector<std::pair<std::string, std::string>> rows = {
155+
{"Create owner empty", "construct_destruct_owner_empty"},
156+
{"Create owner", "construct_destruct_owner"},
157+
{"Create owner factory", "construct_destruct_owner_factory"},
158+
{"Dereference owner", "dereference_owner"},
159+
{"Create observer empty", "construct_destruct_weak_empty"},
160+
{"Create observer", "construct_destruct_weak"},
161+
{"Create observer copy", "construct_destruct_weak_copy"},
162+
{"Dereference observer", "dereference_weak"},
163+
};
164+
165+
std::vector<std::string> cols = {"weak/shared", "observer/obs_unique", "observer/obs_sealed"};
166+
167+
std::cout << "| Pointer | raw/unique | ";
168+
for (const auto& t : cols) {
169+
std::cout << t << " | ";
170+
}
171+
std::cout << std::endl;
172+
173+
std::cout << "|---|---|";
174+
for (const auto& t : cols) {
175+
std::cout << "---|";
176+
}
177+
std::cout << std::endl;
178+
179+
for (const auto& r : rows) {
180+
std::cout << "| " << r.first << " | 1 | ";
181+
for (const auto& t : cols) {
182+
if (r.second == "construct_destruct_owner" && t == "observer/obs_sealed") {
183+
std::cout << "N/A | ";
184+
} else {
185+
std::cout << round1(median(results[r.second][t])) << " | ";
186+
}
187+
}
188+
std::cout << std::endl;
189+
}
190+
103191
return 0;
104192
}

0 commit comments

Comments
 (0)