]>
Commit | Line | Data |
---|---|---|
ef890b79 | 1 | #pragma once |
7ad71bdf FM |
2 | #pragma GCC diagnostic push |
3 | #pragma GCC diagnostic ignored "-Wunused-parameter" | |
d65e98fd | 4 | #if __clang_major__ >= 15 |
7ad71bdf | 5 | #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy" |
d65e98fd | 6 | #endif |
ef890b79 | 7 | #include <boost/accumulators/accumulators.hpp> |
8 | #include <boost/accumulators/statistics.hpp> | |
7ad71bdf | 9 | #pragma GCC diagnostic pop |
ef890b79 | 10 | |
11 | #include <vector> | |
12 | #include <fstream> | |
13 | #include <deque> | |
14 | #include <map> | |
15 | ||
16 | struct LogHistogramBin | |
17 | { | |
18 | double percentile; | |
19 | double latLimit; | |
20 | double latAverage; | |
21 | double latMedian; | |
22 | double latStddev; | |
23 | uint64_t count; | |
24 | double cumulLatAverage; | |
25 | double cumulLatMedian; | |
26 | }; | |
27 | ||
28 | template<typename T> | |
4caba288 | 29 | std::vector<LogHistogramBin> createLogHistogram(const T& bins) |
ef890b79 | 30 | { |
4caba288 | 31 | std::deque<double> percentiles={0.001, 0.01, 0.1, 0.2, 0.5, 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 94, 95, 96, 97, 97.5, 98, 98.5, 99, 99.5, 99.6, 99.9, 99.99, 99.999, 99.9999}; |
ef890b79 | 32 | uint64_t totcumul=0, sum=0; |
33 | ||
34 | for(const auto& c: bins) { | |
35 | totcumul += c.second; | |
36 | } | |
37 | ||
38 | namespace ba=boost::accumulators; | |
39 | ba::accumulator_set<double, ba::features<ba::tag::mean, ba::tag::median, ba::tag::variance>, unsigned> acc; | |
40 | ||
41 | ba::accumulator_set<double, ba::features<ba::tag::mean, ba::tag::median, ba::tag::variance>, unsigned int> cumulstats; | |
42 | ||
43 | uint64_t bincount=0; | |
44 | std::vector<LogHistogramBin> ret; | |
45 | for(const auto& c: bins) { | |
46 | if(percentiles.empty()) | |
47 | break; | |
48 | sum += c.second; | |
49 | bincount += c.second; | |
fc5d04c9 | 50 | |
ef890b79 | 51 | acc(c.first/1000.0, ba::weight=c.second); |
52 | for(unsigned int i=0; i < c.second; ++i) | |
53 | cumulstats(c.first/1000.0, ba::weight=1); // "weighted" does not work for median | |
54 | if(sum > percentiles.front() * totcumul / 100.0) { | |
55 | ret.push_back({100.0-percentiles.front(), (double)c.first/1000.0, ba::mean(acc), ba::median(acc), sqrt(ba::variance(acc)), bincount, ba::mean(cumulstats), ba::median(cumulstats)}); | |
fc5d04c9 | 56 | |
ef890b79 | 57 | percentiles.pop_front(); |
58 | acc=decltype(acc)(); | |
59 | bincount=0; | |
60 | } | |
61 | } | |
62 | std::sort(ret.begin(), ret.end(), [](const LogHistogramBin& a, const LogHistogramBin& b) { | |
63 | return a.percentile < b.percentile; | |
64 | }); | |
65 | return ret; | |
66 | } | |
67 | ||
68 | template<typename T> | |
4caba288 | 69 | void writeLogHistogramFile(const T& bins, std::ostream& out) |
ef890b79 | 70 | { |
4caba288 | 71 | auto vec = createLogHistogram(bins); |
ef890b79 | 72 | out<< R"(# set logscale xy |
73 | # set mxtics 10 | |
74 | # set mytics 10 | |
75 | # set grid xtics | |
76 | # set grid ytics | |
77 | # set xlabel "Slowest percentile" | |
78 | # set ylabel "Millisecond response time" | |
79 | # set terminal svg | |
80 | # set output 'log-histogram.svg' | |
81 | # plot 'log-histogram' using 1:2 with linespoints title 'Average latency per percentile', \ | |
82 | # 'log-histogram' using 1:6 with linespoints title 'Cumulative average latency', \ | |
83 | # 'log-histogram' using 1:7 with linespoints title 'Cumulative median latency')"<<"\n"; | |
84 | ||
85 | out<<"# slow-percentile usec-latency-mean usec-latency-max usec-latency-median usec-latency-stddev usec-latency-cumul usec-latency-median-cumul num-queries\n"; | |
fc5d04c9 FM |
86 | |
87 | ||
ef890b79 | 88 | for(const auto& e : vec) { |
89 | out<<e.percentile<<" "<<e.latAverage<<" "<<e.latLimit<<" "<<e.latMedian<<" "<<e.latStddev<<" "<<e.cumulLatAverage<<" "<<e.cumulLatMedian<<" "<<e.count<<"\n"; | |
90 | } | |
91 | out.flush(); | |
92 | } | |
93 | ||
94 | template<typename T> | |
95 | void writeFullHistogramFile(const T& bins, double binMsec, std::ofstream& out) | |
96 | { | |
97 | std::map<unsigned int, uint64_t> reducedBins; | |
98 | for(const auto& b : bins) { | |
99 | reducedBins[b.first/(1000.0*binMsec)]+=b.second; | |
100 | } | |
101 | out<<"# msec-bin-low count\n"; | |
102 | for(const auto& rb : reducedBins) { | |
103 | out<<rb.first*binMsec<<" "<<rb.second<<"\n"; | |
104 | } | |
105 | out.flush(); | |
106 | } |