1 /* Copyright (C) 2011-2017 Alexey Kopytov.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2 of the License, or
6    (at your option) any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #ifndef SB_HISTOGRAM_H
19 #define SB_HISTOGRAM_H
20 
21 #include <stdint.h>
22 
23 #ifdef HAVE_PTHREAD_H
24 # include <pthread.h>
25 #endif
26 
27 typedef struct {
28   /*
29      Cumulative histogram array. Updated 'on demand' by
30      sb_histogram_get_pct_intermediate(). Protected by 'lock'.
31   */
32   uint64_t              *cumulative_array;
33   /*
34      Total number of events in cumulative_array. Updated on demand by
35      sb_histogram_get_pct_intermediate(). Protected by 'lock'.
36   */
37   uint64_t              cumulative_nevents;
38   /*
39     Temporary array for intermediate percentile calculations. Protected by
40     'lock'.
41   */
42   uint64_t              *temp_array;
43   /*
44      Intermediate histogram values are split into multiple slots and updated
45      with atomics. Aggregations into cumulative values is performed by
46      sb_histogram_get_pct_intermediate() function.
47   */
48   uint64_t              **interm_slots;
49   /* Number of elements in each array */
50   size_t                array_size;
51   /* Lower bound of values to track */
52   double                range_min;
53   /* Upper bound of values to track */
54   double                range_max;
55   /* Value to deduct to calculate histogram range based on array element */
56   double                range_deduct;
57   /* Value to multiply to calculate histogram range based array element */
58   double                range_mult;
59   /*
60      rwlock to protect cumulative_array and cumulative_nevents from concurrent
61      updates.
62   */
63   pthread_rwlock_t      lock;
64 } sb_histogram_t;
65 
66 /* Global latency histogram */
67 extern sb_histogram_t sb_latency_histogram;
68 
69 /*
70   Allocate a new histogram and initialize it with sb_histogram_init().
71 */
72 sb_histogram_t *sb_histogram_new(size_t size, double range_min,
73                                  double range_max);
74 
75 /*
76   Deallocate a histogram allocated with sb_histogram_new().
77 */
78 void sb_histogram_delete(sb_histogram_t *h);
79 
80 /*
81   Initialize a new histogram object with a given array size and value bounds.
82 */
83 int sb_histogram_init(sb_histogram_t *h, size_t size,
84                       double range_min, double range_max);
85 
86 /* Update histogram with a given value. */
87 void sb_histogram_update(sb_histogram_t *h, double value);
88 
89 /*
90   Calculate a given percentile value from the intermediate histogram values,
91   then merge intermediate values into cumulative ones atomically, i.e. in a way
92   that no concurrent updates are lost and will be accounted in either the
93   current or later merge of intermediate clues.
94 */
95 double sb_histogram_get_pct_intermediate(sb_histogram_t *h, double percentile);
96 
97 /*
98   Merge intermediate histogram values into cumulative ones and calculate a given
99   percentile value from the cumulative array.
100 */
101 double sb_histogram_get_pct_cumulative(sb_histogram_t *h, double percentile);
102 
103 /*
104    Similar to sb_histogram_get_pct_cumulative(), but also resets cumulative
105    stats right after calculating the returned percentile. The reset happens
106    atomically so that no conucrrent updates are lost after percentile
107    calculation. This is currently used only by 'checkpoint' reports.
108 */
109 double sb_histogram_get_pct_checkpoint(sb_histogram_t *h, double percentile);
110 
111 /*
112   Print a given histogram to stdout
113 */
114 void sb_histogram_print(sb_histogram_t *h);
115 
116 /* Destroy a given histogram object */
117 void sb_histogram_done(sb_histogram_t *h);
118 
119 #endif
120