37 #include <boost/chrono.hpp> 38 #include <boost/regex.hpp> 48 typedef boost::chrono::high_resolution_clock
clock;
52 m_base = clock::now();
57 m_start = clock::now();
62 clock::duration elapsed = clock::now() - m_start;
63 return static_cast<int>(boost::chrono::duration_cast<boost::chrono::milliseconds>(elapsed).
count());
67 clock::time_point m_base;
68 clock::time_point m_start;
86 , m_per_call_timers(
T::loop_count * params.loop_multiplier, {
true})
92 static_assert(0 < T::loop_count,
"T::loop_count must be greater than 0");
102 std::cout <<
"Warm up: " << timer.
elapsed_ms() <<
" ms" << std::endl;
108 m_per_call_timers[i].resume();
112 m_per_call_timers[i].pause();
121 size_t get_size()
const {
return m_stats->get_size(); }
125 static_assert(0 < T::loop_count,
"T::loop_count must be greater than 0");
131 double get_mean()
const {
return m_stats->get_mean(); }
133 double get_stddev()
const {
return m_stats->get_standard_deviation(); }
135 std::vector<uint64_t>
get_quantiles(
size_t n)
const {
return m_stats->get_quantiles(n); }
139 return m_stats->is_same_distribution_99(npoints, mean, stddev);
148 const size_t warm_up_rounds = 1000 * 1000 * 1000;
150 for (
size_t i = 0; i < warm_up_rounds; ++i)
161 std::vector<tools::PerformanceTimer> m_per_call_timers;
162 std::unique_ptr<Stats<tools::PerformanceTimer, uint64_t>> m_stats;
165 template <
typename T>
169 if (!filter.empty() && !boost::regex_match(
std::string(test_name), match, boost::regex(filter)))
177 std::cout << test_name <<
" - OK:\n";
178 std::cout <<
" loop count: " << T::loop_count * params.
loop_multiplier <<
'\n';
179 std::cout <<
" elapsed: " << runner.
elapsed_time() <<
" ms\n";
182 std::cout <<
" min: " << runner.
get_min() <<
" ns\n";
183 std::cout <<
" max: " << runner.
get_max() <<
" ns\n";
184 std::cout <<
" median: " << runner.
get_median() <<
" ns\n";
185 std::cout <<
" std dev: " << runner.
get_stddev() <<
" ns\n";
190 std::cout << test_name <<
" (" << T::loop_count * params.
loop_multiplier <<
" calls) - OK:";
192 const char *
unit =
"ms";
193 double scale = 1000000;
195 if (time_per_call < 100) {
212 std::vector<TimingsDatabase::instance> prev_instances = params.
td.
get(test_name);
213 params.
td.
add(test_name, {
time(NULL), runner.
get_size(), min, max, mean, med, stddev, npskew, quantiles});
215 std::cout << (params.
verbose ?
" time per call: " :
" ") << time_per_call <<
" " <<
unit <<
"/call" << (params.
verbose ?
"\n" :
"");
221 uint64_t p95s = quantiles[9] / scale;
224 if (!prev_instances.empty())
229 double pc = fabs(100. * (prev_instance.
mean - runner.
get_mean()) / prev_instance.
mean);
230 cmp =
", " +
std::to_string(pc) +
"% " + (mean > prev_instance.
mean ?
"slower" :
"faster");
234 std::cout <<
" (min " << mins <<
" " <<
unit <<
", 90th " << p95s <<
" " <<
unit <<
", median " << meds <<
" " <<
unit <<
", std dev " << stddevs <<
" " <<
unit <<
")" << cmp;
236 std::cout << std::endl;
240 std::cout << test_name <<
" - FAILED" << std::endl;
244 #define QUOTEME(x) #x 245 #define TEST_PERFORMANCE0(filter, params, test_class) run_test< test_class >(filter, params, QUOTEME(test_class)) 246 #define TEST_PERFORMANCE1(filter, params, test_class, a0) run_test< test_class<a0> >(filter, params, QUOTEME(test_class<a0>)) 247 #define TEST_PERFORMANCE2(filter, params, test_class, a0, a1) run_test< test_class<a0, a1> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ">") 248 #define TEST_PERFORMANCE3(filter, params, test_class, a0, a1, a2) run_test< test_class<a0, a1, a2> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ">") 249 #define TEST_PERFORMANCE4(filter, params, test_class, a0, a1, a2, a3) run_test< test_class<a0, a1, a2, a3> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ", " QUOTEME(a3) ">") 250 #define TEST_PERFORMANCE5(filter, params, test_class, a0, a1, a2, a3, a4) run_test< test_class<a0, a1, a2, a3, a4> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ", " QUOTEME(a3) ", " QUOTEME(a4) ">") 251 #define TEST_PERFORMANCE6(filter, params, test_class, a0, a1, a2, a3, a4, a5) run_test< test_class<a0, a1, a2, a3, a4, a5> >(filter, params, QUOTEME(test_class) "<" QUOTEME(a0) ", " QUOTEME(a1) ", " QUOTEME(a2) ", " QUOTEME(a3) ", " QUOTEME(a4) ", " QUOTEME(a5) ">")
double get_non_parametric_skew() const
test_runner(const Params ¶ms)
std::vector< instance > get(const char *name) const
int time_per_call(int scale=1) const
mdb_size_t count(MDB_cursor *cur)
double get_stddev() const
std::vector< uint64_t > get_quantiles(size_t n) const
unsigned __int64 uint64_t
const base::type::char_t * unit
bool is_same_distribution(size_t npoints, double mean, double stddev) const
std::string to_string(t_connection_type type)
uint64_t get_median() const
void add(const char *name, const instance &data)