histogram.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
22 
23 #include <math.h>
24 #include <stddef.h>
25 #include <string.h>
26 
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
29 
31 
32 /* Histograms are stored with exponentially increasing bucket sizes.
33  The first bucket is [0, m) where m = 1 + resolution
34  Bucket n (n>=1) contains [m**n, m**(n+1))
35  There are sufficient buckets to reach max_bucket_start */
36 
38  /* Sum of all values seen so far */
39  double sum;
40  /* Sum of squares of all values seen so far */
42  /* number of values seen so far */
43  double count;
44  /* m in the description */
45  double multiplier;
47  /* minimum value seen */
48  double min_seen;
49  /* maximum value seen */
50  double max_seen;
51  /* maximum representable value */
52  double max_possible;
53  /* number of buckets */
54  size_t num_buckets;
55  /* the buckets themselves */
57 };
58 
59 /* determine a bucket index given a value - does no bounds checking */
60 static size_t bucket_for_unchecked(grpc_histogram* h, double x) {
61  return static_cast<size_t>(log(x) * h->one_on_log_multiplier);
62 }
63 
64 /* bounds checked version of the above */
65 static size_t bucket_for(grpc_histogram* h, double x) {
66  size_t bucket =
67  bucket_for_unchecked(h, grpc_core::Clamp(x, 1.0, h->max_possible));
68  GPR_ASSERT(bucket < h->num_buckets);
69  return bucket;
70 }
71 
72 /* at what value does a bucket start? */
73 static double bucket_start(grpc_histogram* h, double x) {
74  return pow(h->multiplier, x);
75 }
76 
78  double max_bucket_start) {
79  grpc_histogram* h =
80  static_cast<grpc_histogram*>(gpr_malloc(sizeof(grpc_histogram)));
81  GPR_ASSERT(resolution > 0.0);
82  GPR_ASSERT(max_bucket_start > resolution);
83  h->sum = 0.0;
84  h->sum_of_squares = 0.0;
85  h->multiplier = 1.0 + resolution;
86  h->one_on_log_multiplier = 1.0 / log(1.0 + resolution);
87  h->max_possible = max_bucket_start;
88  h->count = 0.0;
89  h->min_seen = max_bucket_start;
90  h->max_seen = 0.0;
91  h->num_buckets = bucket_for_unchecked(h, max_bucket_start) + 1;
92  GPR_ASSERT(h->num_buckets > 1);
93  GPR_ASSERT(h->num_buckets < 100000000);
94  h->buckets =
95  static_cast<uint32_t*>(gpr_zalloc(sizeof(uint32_t) * h->num_buckets));
96  return h;
97 }
98 
100  gpr_free(h->buckets);
101  gpr_free(h);
102 }
103 
105  h->sum += x;
106  h->sum_of_squares += x * x;
107  h->count++;
108  if (x < h->min_seen) {
109  h->min_seen = x;
110  }
111  if (x > h->max_seen) {
112  h->max_seen = x;
113  }
114  h->buckets[bucket_for(h, x)]++;
115 }
116 
118  if ((dst->num_buckets != src->num_buckets) ||
119  (dst->multiplier != src->multiplier)) {
120  /* Fail because these histograms don't match */
121  return 0;
122  }
124  src->min_seen, src->max_seen, src->sum,
125  src->sum_of_squares, src->count);
126  return 1;
127 }
128 
130  const uint32_t* data, size_t data_count,
131  double min_seen, double max_seen, double sum,
132  double sum_of_squares, double count) {
133  size_t i;
134  GPR_ASSERT(histogram->num_buckets == data_count);
135  histogram->sum += sum;
136  histogram->sum_of_squares += sum_of_squares;
137  histogram->count += count;
138  if (min_seen < histogram->min_seen) {
139  histogram->min_seen = min_seen;
140  }
141  if (max_seen > histogram->max_seen) {
142  histogram->max_seen = max_seen;
143  }
144  for (i = 0; i < histogram->num_buckets; i++) {
145  histogram->buckets[i] += data[i];
146  }
147 }
148 
149 static double threshold_for_count_below(grpc_histogram* h, double count_below) {
150  double count_so_far;
151  double lower_bound;
152  double upper_bound;
153  size_t lower_idx;
154  size_t upper_idx;
155 
156  if (h->count == 0) {
157  return 0.0;
158  }
159 
160  if (count_below <= 0) {
161  return h->min_seen;
162  }
163  if (count_below >= h->count) {
164  return h->max_seen;
165  }
166 
167  /* find the lowest bucket that gets us above count_below */
168  count_so_far = 0.0;
169  for (lower_idx = 0; lower_idx < h->num_buckets; lower_idx++) {
170  count_so_far += h->buckets[lower_idx];
171  if (count_so_far >= count_below) {
172  break;
173  }
174  }
175  if (count_so_far == count_below) {
176  /* this bucket hits the threshold exactly... we should be midway through
177  any run of zero values following the bucket */
178  for (upper_idx = lower_idx + 1; upper_idx < h->num_buckets; upper_idx++) {
179  if (h->buckets[upper_idx]) {
180  break;
181  }
182  }
183  return (bucket_start(h, static_cast<double>(lower_idx)) +
184  bucket_start(h, static_cast<double>(upper_idx))) /
185  2.0;
186  } else {
187  /* treat values as uniform throughout the bucket, and find where this value
188  should lie */
189  lower_bound = bucket_start(h, static_cast<double>(lower_idx));
190  upper_bound = bucket_start(h, static_cast<double>(lower_idx + 1));
191  return grpc_core::Clamp(upper_bound - (upper_bound - lower_bound) *
192  (count_so_far - count_below) /
193  h->buckets[lower_idx],
194  h->min_seen, h->max_seen);
195  }
196 }
197 
199  return threshold_for_count_below(h, h->count * percentile / 100.0);
200 }
201 
203  GPR_ASSERT(h->count != 0);
204  return h->sum / h->count;
205 }
206 
208  return sqrt(grpc_histogram_variance(h));
209 }
210 
212  if (h->count == 0) return 0.0;
213  return (h->sum_of_squares * h->count - h->sum * h->sum) /
214  (h->count * h->count);
215 }
216 
217 double grpc_histogram_maximum(grpc_histogram* h) { return h->max_seen; }
218 
219 double grpc_histogram_minimum(grpc_histogram* h) { return h->min_seen; }
220 
221 double grpc_histogram_count(grpc_histogram* h) { return h->count; }
222 
223 double grpc_histogram_sum(grpc_histogram* h) { return h->sum; }
224 
226  return h->sum_of_squares;
227 }
228 
230  size_t* count) {
232  return histogram->buckets;
233 }
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
grpc_histogram_merge_contents
void grpc_histogram_merge_contents(grpc_histogram *histogram, const uint32_t *data, size_t data_count, double min_seen, double max_seen, double sum, double sum_of_squares, double count)
Definition: histogram.cc:129
bucket_for_unchecked
static size_t bucket_for_unchecked(grpc_histogram *h, double x)
Definition: histogram.cc:60
log.h
grpc_histogram::buckets
uint32_t * buckets
Definition: histogram.cc:56
grpc_histogram::num_buckets
size_t num_buckets
Definition: histogram.cc:54
grpc::testing::sum
double sum(const T &container, F functor)
Definition: test/cpp/qps/stats.h:30
string.h
grpc_histogram::max_possible
double max_possible
Definition: histogram.cc:52
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
useful.h
gpr_malloc
GPRAPI void * gpr_malloc(size_t size)
Definition: alloc.cc:29
grpc_histogram::count
double count
Definition: histogram.cc:43
profile_analyzer.percentile
def percentile(N, percent, key=lambda x:x)
Definition: profile_analyzer.py:187
grpc_histogram_minimum
double grpc_histogram_minimum(grpc_histogram *h)
Definition: histogram.cc:219
gpr_zalloc
GPRAPI void * gpr_zalloc(size_t size)
Definition: alloc.cc:40
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
threshold_for_count_below
static double threshold_for_count_below(grpc_histogram *h, double count_below)
Definition: histogram.cc:149
grpc_histogram_count
double grpc_histogram_count(grpc_histogram *h)
Definition: histogram.cc:221
grpc_histogram_destroy
void grpc_histogram_destroy(grpc_histogram *h)
Definition: histogram.cc:99
grpc_histogram
Definition: histogram.cc:37
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
grpc_histogram::min_seen
double min_seen
Definition: histogram.cc:48
histogram
static grpc_histogram * histogram
Definition: test/core/fling/client.cc:34
bucket_start
static double bucket_start(grpc_histogram *h, double x)
Definition: histogram.cc:73
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
bucket_for
static size_t bucket_for(grpc_histogram *h, double x)
Definition: histogram.cc:65
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
grpc_histogram_percentile
double grpc_histogram_percentile(grpc_histogram *h, double percentile)
Definition: histogram.cc:198
grpc_histogram::one_on_log_multiplier
double one_on_log_multiplier
Definition: histogram.cc:46
histogram.h
grpc_histogram_stddev
double grpc_histogram_stddev(grpc_histogram *h)
Definition: histogram.cc:207
grpc_histogram_variance
double grpc_histogram_variance(grpc_histogram *h)
Definition: histogram.cc:211
grpc_histogram_create
grpc_histogram * grpc_histogram_create(double resolution, double max_bucket_start)
Definition: histogram.cc:77
grpc_histogram::multiplier
double multiplier
Definition: histogram.cc:45
grpc_core::Clamp
T Clamp(T val, T min, T max)
Definition: useful.h:31
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
grpc_histogram::sum_of_squares
double sum_of_squares
Definition: histogram.cc:41
alloc.h
grpc_histogram_maximum
double grpc_histogram_maximum(grpc_histogram *h)
Definition: histogram.cc:217
grpc_histogram::sum
double sum
Definition: histogram.cc:39
grpc_histogram_sum
double grpc_histogram_sum(grpc_histogram *h)
Definition: histogram.cc:223
log
bool log
Definition: abseil-cpp/absl/synchronization/mutex.cc:310
grpc_histogram::max_seen
double max_seen
Definition: histogram.cc:50
grpc_histogram_sum_of_squares
double grpc_histogram_sum_of_squares(grpc_histogram *h)
Definition: histogram.cc:225
grpc_histogram_mean
double grpc_histogram_mean(grpc_histogram *h)
Definition: histogram.cc:202
grpc_histogram_add
void grpc_histogram_add(grpc_histogram *h, double x)
Definition: histogram.cc:104
grpc_histogram_get_contents
const uint32_t * grpc_histogram_get_contents(grpc_histogram *histogram, size_t *count)
Definition: histogram.cc:229
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
grpc_histogram_merge
int grpc_histogram_merge(grpc_histogram *dst, const grpc_histogram *src)
Definition: histogram.cc:117
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:12