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