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