]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/histog.hh
Correct doc for ecs-add-for default
[thirdparty/pdns.git] / pdns / histog.hh
CommitLineData
ef890b79 1#pragma once
ef890b79 2#include <boost/accumulators/accumulators.hpp>
3#include <boost/accumulators/statistics.hpp>
4
5#include <vector>
6#include <fstream>
7#include <deque>
8#include <map>
9
10struct LogHistogramBin
11{
12 double percentile;
13 double latLimit;
14 double latAverage;
15 double latMedian;
16 double latStddev;
17 uint64_t count;
18 double cumulLatAverage;
19 double cumulLatMedian;
20};
21
22template<typename T>
23std::vector<LogHistogramBin> createLogHistogram(const T& bins,
24 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})
25{
26 uint64_t totcumul=0, sum=0;
27
28 for(const auto& c: bins) {
29 totcumul += c.second;
30 }
31
32 namespace ba=boost::accumulators;
33 ba::accumulator_set<double, ba::features<ba::tag::mean, ba::tag::median, ba::tag::variance>, unsigned> acc;
34
35 ba::accumulator_set<double, ba::features<ba::tag::mean, ba::tag::median, ba::tag::variance>, unsigned int> cumulstats;
36
37 uint64_t bincount=0;
38 std::vector<LogHistogramBin> ret;
39 for(const auto& c: bins) {
40 if(percentiles.empty())
41 break;
42 sum += c.second;
43 bincount += c.second;
44
45 acc(c.first/1000.0, ba::weight=c.second);
46 for(unsigned int i=0; i < c.second; ++i)
47 cumulstats(c.first/1000.0, ba::weight=1); // "weighted" does not work for median
48 if(sum > percentiles.front() * totcumul / 100.0) {
49 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)});
50
51 percentiles.pop_front();
52 acc=decltype(acc)();
53 bincount=0;
54 }
55 }
56 std::sort(ret.begin(), ret.end(), [](const LogHistogramBin& a, const LogHistogramBin& b) {
57 return a.percentile < b.percentile;
58 });
59 return ret;
60}
61
62template<typename T>
63void writeLogHistogramFile(const T& bins, std::ostream& out, 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} )
64{
65
66 auto vec = createLogHistogram(bins, percentiles);
67 out<< R"(# set logscale xy
68# set mxtics 10
69# set mytics 10
70# set grid xtics
71# set grid ytics
72# set xlabel "Slowest percentile"
73# set ylabel "Millisecond response time"
74# set terminal svg
75# set output 'log-histogram.svg'
76# plot 'log-histogram' using 1:2 with linespoints title 'Average latency per percentile', \
77# 'log-histogram' using 1:6 with linespoints title 'Cumulative average latency', \
78# 'log-histogram' using 1:7 with linespoints title 'Cumulative median latency')"<<"\n";
79
80 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";
81
82
83 for(const auto& e : vec) {
84 out<<e.percentile<<" "<<e.latAverage<<" "<<e.latLimit<<" "<<e.latMedian<<" "<<e.latStddev<<" "<<e.cumulLatAverage<<" "<<e.cumulLatMedian<<" "<<e.count<<"\n";
85 }
86 out.flush();
87}
88
89template<typename T>
90void writeFullHistogramFile(const T& bins, double binMsec, std::ofstream& out)
91{
92 std::map<unsigned int, uint64_t> reducedBins;
93 for(const auto& b : bins) {
94 reducedBins[b.first/(1000.0*binMsec)]+=b.second;
95 }
96 out<<"# msec-bin-low count\n";
97 for(const auto& rb : reducedBins) {
98 out<<rb.first*binMsec<<" "<<rb.second<<"\n";
99 }
100 out.flush();
101}