11#include " speed_benchmark_common.hpp"
22
3+ #include < algorithm>
34#include < cmath>
5+ #include < iomanip>
6+ #include < unordered_map>
7+ #include < vector>
48
59template <typename B, typename F>
610auto 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+
53106template <typename T>
54107void 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