1 #include <math.h>
2 #include "timer.h"
3
4 /* Static declarations */
5 static void finalize_timer(timer *timer);
6
7 /**
8 * Initializes the timer struct
9 * @arg eps The maximum error for the quantiles
10 * @arg quantiles A sorted array of double quantile values, must be on (0, 1)
11 * @arg num_quants The number of entries in the quantiles array
12 * @arg timeer The timer struct to initialize
13 * @return 0 on success.
14 */
init_timer(double eps,double * quantiles,uint32_t num_quants,timer * timer)15 int init_timer(double eps, double *quantiles, uint32_t num_quants, timer *timer) {
16 timer->actual_count = 0;
17 timer->count = 0;
18 timer->sum = 0;
19 timer->squared_sum = 0;
20 timer->finalized = 1;
21 int res = init_cm_quantile(eps, quantiles, num_quants, &timer->cm);
22 return res;
23 }
24
25 /**
26 * Destroy the timer struct.
27 * @arg timer The timer to destroy
28 * @return 0 on success.
29 */
destroy_timer(timer * timer)30 int destroy_timer(timer *timer) {
31 return destroy_cm_quantile(&timer->cm);
32 }
33
34 /**
35 * Adds a new sample to the struct
36 * @arg timer The timer to add to
37 * @arg sample The new sample value
38 * @arg sample_rate The sample rate
39 * @return 0 on success.
40 */
timer_add_sample(timer * timer,double sample,double sample_rate)41 int timer_add_sample(timer *timer, double sample, double sample_rate) {
42 timer->actual_count += 1;
43 timer->count += (1 / sample_rate);
44 timer->sum += sample;
45 timer->squared_sum += pow(sample, 2);
46 timer->finalized = 0;
47 return cm_add_sample(&timer->cm, sample);
48 }
49
50 /**
51 * Queries for a quantile value
52 * @arg timer The timer to query
53 * @arg quantile The quantile to query
54 * @return The value on success or 0.
55 */
timer_query(timer * timer,double quantile)56 double timer_query(timer *timer, double quantile) {
57 finalize_timer(timer);
58 return cm_query(&timer->cm, quantile);
59 }
60
61 /**
62 * Returns the number of samples in the timer
63 * @arg timer The timer to query
64 * @return The number of samples
65 */
timer_count(timer * timer)66 uint64_t timer_count(timer *timer) {
67 return timer->count;
68 }
69
70 /**
71 * Returns the minimum timer value
72 * @arg timer The timer to query
73 * @return The number of samples
74 */
timer_min(timer * timer)75 double timer_min(timer *timer) {
76 finalize_timer(timer);
77 if (!timer->cm.samples) return 0;
78 return timer->cm.samples->value;
79 }
80
81 /**
82 * Returns the mean timer value
83 * @arg timer The timer to query
84 * @return The mean value
85 */
timer_mean(timer * timer)86 double timer_mean(timer *timer) {
87 return (timer->actual_count) ? timer->sum / timer->actual_count : 0;
88 }
89
90 /**
91 * Returns the sample standard deviation timer value
92 * @arg timer The timer to query
93 * @return The sample standard deviation
94 */
timer_stddev(timer * timer)95 double timer_stddev(timer *timer) {
96 double num = (timer->actual_count * timer->squared_sum) - pow(timer->sum, 2);
97 double div = timer->actual_count * (timer->actual_count - 1);
98 if (div == 0) return 0;
99 return sqrt(num / div);
100 }
101
102 /**
103 * Returns the sum of the timer
104 * @arg timer The timer to query
105 * @return The sum of values
106 */
timer_sum(timer * timer)107 double timer_sum(timer *timer) {
108 return timer->sum;
109 }
110
111 /**
112 * Returns the sum squared of the timer
113 * @arg timer The timer to query
114 * @return The sum squared of values
115 */
timer_squared_sum(timer * timer)116 double timer_squared_sum(timer *timer) {
117 return timer->squared_sum;
118 }
119
120 /**
121 * Returns the maximum timer value
122 * @arg timer The timer to query
123 * @return The maximum value
124 */
timer_max(timer * timer)125 double timer_max(timer *timer) {
126 finalize_timer(timer);
127 if (!timer->cm.end) return 0;
128 return timer->cm.end->value;
129 }
130
131 // Finalizes the timer for queries
finalize_timer(timer * timer)132 static void finalize_timer(timer *timer) {
133 if (timer->finalized) return;
134
135 // Force the quantile to flush internal
136 // buffers so that queries are accurate.
137 cm_flush(&timer->cm);
138
139 timer->finalized = 1;
140 }
141