Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
platform_timer_accuracy.cpp
Go to the documentation of this file.
3
4#include <fc/time.hpp>
5#include <fc/log/logger.hpp>
6
7#include <boost/accumulators/accumulators.hpp>
8#include <boost/accumulators/statistics/stats.hpp>
9#include <boost/accumulators/statistics/min.hpp>
10#include <boost/accumulators/statistics/max.hpp>
11#include <boost/accumulators/statistics/weighted_mean.hpp>
12#include <boost/accumulators/statistics/weighted_variance.hpp>
13
14#include <chrono>
15#include <mutex>
16
17namespace sysio { namespace chain {
18
19namespace bacc = boost::accumulators;
20
22 static std::mutex m;
23 static bool once_is_enough;
24
25 std::lock_guard guard(m);
26
27 if(once_is_enough)
28 return;
29
30 bacc::accumulator_set<int, bacc::stats<bacc::tag::mean, bacc::tag::min, bacc::tag::max, bacc::tag::variance>, float> samples;
31
32 //keep longest first in list. You're effectively going to take test_intervals[0]*sizeof(test_intervals[0])
33 //time to do the the test
34 int test_intervals[] = {50000, 10000, 5000, 1000, 500, 100, 50, 10};
35
36 for(int& interval : test_intervals) {
37 unsigned int loops = test_intervals[0]/interval;
38
39 for(unsigned int i = 0; i < loops; ++i) {
40 auto start = std::chrono::high_resolution_clock::now();
41 timer.start(fc::time_point(fc::time_point::now().time_since_epoch() + fc::microseconds(interval)));
42 while(!timer.expired) {}
43 auto end = std::chrono::high_resolution_clock::now();
44 int timer_slop = std::chrono::duration_cast<std::chrono::microseconds>(end-start).count() - interval;
45
46 //since more samples are run for the shorter expirations, weigh the longer expirations accordingly. This
47 //helps to make a few results more fair. Two such examples: AWS c4&i5 xen instances being rather stable
48 //down to 100us but then struggling with 50us and 10us. MacOS having performance that seems to correlate
49 //with expiry length; that is, long expirations have high error, short expirations have low error.
50 //That said, for these platforms, a tighter tolerance may possibly be achieved by taking performance
51 //metrics in mulitple bins and appliying the slop based on which bin a deadline resides in. Not clear
52 //if that's worth the extra complexity at this point.
53 samples(timer_slop, bacc::weight = interval/(float)test_intervals[0]);
54 }
55 }
56
57 #define TIMER_STATS_FORMAT "min:${min}us max:${max}us mean:${mean}us stddev:${stddev}us"
58 #define TIMER_STATS \
59 ("min", bacc::min(samples))("max", bacc::max(samples)) \
60 ("mean", (int)bacc::mean(samples))("stddev", (int)sqrt(bacc::variance(samples)))
61
62 ilog("Checktime timer accuracy: " TIMER_STATS_FORMAT, TIMER_STATS);
63 if(bacc::mean(samples) + sqrt(bacc::variance(samples))*2 > 250)
64 wlog("Checktime timer accuracy on this platform and hardware combination is poor; accuracy of subjective transaction deadline enforcement will suffer");
65
66 once_is_enough = true;
67}
68
69}}
static time_point now()
Definition time.cpp:14
#define wlog(FORMAT,...)
Definition logger.hpp:124
#define ilog(FORMAT,...)
Definition logger.hpp:118
void compute_and_print_timer_accuracy(platform_timer &t)
#define TIMER_STATS_FORMAT
#define TIMER_STATS