aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2017-08-31 12:20:04 -0700
committerGravatar Craig Tiller <ctiller@google.com>2017-08-31 12:20:04 -0700
commit5489d41c15926abbf12a5b8d27b24d1d605d7f0f (patch)
treeda7b27b1b5389607d2e2119b11fb18c0bf51e4f9 /src/core
parent520d76d698f7f03038fd7fcfe1a2129acd0fa948 (diff)
Expose histograms via microbenchmarks
Diffstat (limited to 'src/core')
-rw-r--r--src/core/lib/debug/stats.c67
-rw-r--r--src/core/lib/debug/stats.h8
-rw-r--r--src/core/lib/debug/stats_data.h60
-rw-r--r--src/core/lib/debug/stats_data.yaml23
4 files changed, 125 insertions, 33 deletions
diff --git a/src/core/lib/debug/stats.c b/src/core/lib/debug/stats.c
index cb9c78c4f2..5079ed2ffa 100644
--- a/src/core/lib/debug/stats.c
+++ b/src/core/lib/debug/stats.c
@@ -52,6 +52,16 @@ void grpc_stats_collect(grpc_stats_data *output) {
}
}
+void grpc_stats_diff(const grpc_stats_data *b, const grpc_stats_data *a,
+ grpc_stats_data *c) {
+ for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
+ c->counters[i] = b->counters[i] - a->counters[i];
+ }
+ for (size_t i = 0; i < GRPC_STATS_HISTOGRAM_BUCKETS; i++) {
+ c->histograms[i] = b->histograms[i] - a->histograms[i];
+ }
+}
+
int grpc_stats_histo_find_bucket_slow(grpc_exec_ctx *exec_ctx, double value,
const double *table, int table_size) {
GRPC_STATS_INC_HISTOGRAM_SLOW_LOOKUPS(exec_ctx);
@@ -72,6 +82,63 @@ int grpc_stats_histo_find_bucket_slow(grpc_exec_ctx *exec_ctx, double value,
return a;
}
+size_t grpc_stats_histo_count(const grpc_stats_data *stats,
+ grpc_stats_histograms histogram) {
+ size_t sum = 0;
+ for (int i = 0; i < grpc_stats_histo_buckets[histogram]; i++) {
+ sum += (size_t)stats->histograms[grpc_stats_histo_start[histogram] + i];
+ }
+ return sum;
+}
+
+static double threshold_for_count_below(const gpr_atm *bucket_counts,
+ const double *bucket_boundaries,
+ int num_buckets, double count_below) {
+ double count_so_far;
+ double lower_bound;
+ double upper_bound;
+ int lower_idx;
+ int upper_idx;
+
+ /* find the lowest bucket that gets us above count_below */
+ count_so_far = 0.0;
+ for (lower_idx = 0; lower_idx < num_buckets; lower_idx++) {
+ count_so_far += (double)bucket_counts[lower_idx];
+ if (count_so_far >= count_below) {
+ break;
+ }
+ }
+ if (count_so_far == count_below) {
+ /* this bucket hits the threshold exactly... we should be midway through
+ any run of zero values following the bucket */
+ for (upper_idx = lower_idx + 1; upper_idx < num_buckets; upper_idx++) {
+ if (bucket_counts[upper_idx]) {
+ break;
+ }
+ }
+ return (bucket_boundaries[lower_idx] + bucket_boundaries[upper_idx]) / 2.0;
+ } else {
+ /* treat values as uniform throughout the bucket, and find where this value
+ should lie */
+ lower_bound = bucket_boundaries[lower_idx];
+ upper_bound = bucket_boundaries[lower_idx + 1];
+ return upper_bound -
+ (upper_bound - lower_bound) * (count_so_far - count_below) /
+ (double)bucket_counts[lower_idx];
+ }
+}
+
+double grpc_stats_histo_percentile(const grpc_stats_data *stats,
+ grpc_stats_histograms histogram,
+ double percentile) {
+ size_t count = grpc_stats_histo_count(stats, histogram);
+ if (count == 0) return 0.0;
+ return threshold_for_count_below(
+ stats->histograms + grpc_stats_histo_start[histogram],
+ grpc_stats_histo_bucket_boundaries[histogram],
+ grpc_stats_histo_buckets[histogram], (double)count * percentile / 100.0);
+}
+
char *grpc_stats_data_as_json(const grpc_stats_data *data) {
gpr_strvec v;
char *tmp;
diff --git a/src/core/lib/debug/stats.h b/src/core/lib/debug/stats.h
index c4086063bc..c440ab3b66 100644
--- a/src/core/lib/debug/stats.h
+++ b/src/core/lib/debug/stats.h
@@ -46,8 +46,16 @@ extern grpc_stats_data *grpc_stats_per_cpu_storage;
void grpc_stats_init(void);
void grpc_stats_shutdown(void);
void grpc_stats_collect(grpc_stats_data *output);
+// c = b-a
+void grpc_stats_diff(const grpc_stats_data *b, const grpc_stats_data *a,
+ grpc_stats_data *c);
char *grpc_stats_data_as_json(const grpc_stats_data *data);
int grpc_stats_histo_find_bucket_slow(grpc_exec_ctx *exec_ctx, double value,
const double *table, int table_size);
+double grpc_stats_histo_percentile(const grpc_stats_data *data,
+ grpc_stats_histograms histogram,
+ double percentile);
+size_t grpc_stats_histo_count(const grpc_stats_data *data,
+ grpc_stats_histograms histogram);
#endif
diff --git a/src/core/lib/debug/stats_data.h b/src/core/lib/debug/stats_data.h
index 5d616c73c7..9a4ba68655 100644
--- a/src/core/lib/debug/stats_data.h
+++ b/src/core/lib/debug/stats_data.h
@@ -66,64 +66,72 @@ typedef enum {
GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_HISTOGRAM_SLOW_LOOKUPS)
#define GRPC_STATS_INC_TCP_WRITE_SIZE(exec_ctx, value) \
do { \
- double _hist_val = (double)(value); \
- if (_hist_val < 0) _hist_val = 0; \
- uint64_t _hist_idx = *(uint64_t *)&_hist_val; \
- if (_hist_val < 5.000000) { \
+ union { \
+ double dbl; \
+ uint64_t uint; \
+ } _val; \
+ _val.dbl = (double)(value); \
+ if (_val.dbl < 0) _val.dbl = 0; \
+ if (_val.dbl < 5.000000) { \
GRPC_STATS_INC_HISTOGRAM( \
- (exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_SIZE, (int)_hist_val); \
+ (exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_SIZE, (int)_val.dbl); \
} else { \
- if (_hist_idx < 4715268809856909312ull) { \
+ if (_val.uint < 4715268809856909312ull) { \
GRPC_STATS_INC_HISTOGRAM( \
(exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_SIZE, \
- grpc_stats_table_1[((_hist_idx - 4617315517961601024ull) >> 50)]); \
+ grpc_stats_table_1[((_val.uint - 4617315517961601024ull) >> 50)]); \
} else { \
GRPC_STATS_INC_HISTOGRAM( \
(exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_SIZE, \
- grpc_stats_histo_find_bucket_slow((exec_ctx), (value), \
+ grpc_stats_histo_find_bucket_slow((exec_ctx), _val.dbl, \
grpc_stats_table_0, 64)); \
} \
} \
} while (false)
#define GRPC_STATS_INC_TCP_WRITE_IOV_SIZE(exec_ctx, value) \
do { \
- double _hist_val = (double)(value); \
- if (_hist_val < 0) _hist_val = 0; \
- uint64_t _hist_idx = *(uint64_t *)&_hist_val; \
- if (_hist_val < 12.000000) { \
- GRPC_STATS_INC_HISTOGRAM((exec_ctx), \
- GRPC_STATS_HISTOGRAM_TCP_WRITE_IOV_SIZE, \
- (int)_hist_val); \
+ union { \
+ double dbl; \
+ uint64_t uint; \
+ } _val; \
+ _val.dbl = (double)(value); \
+ if (_val.dbl < 0) _val.dbl = 0; \
+ if (_val.dbl < 12.000000) { \
+ GRPC_STATS_INC_HISTOGRAM( \
+ (exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_IOV_SIZE, (int)_val.dbl); \
} else { \
- if (_hist_idx < 4652218415073722368ull) { \
+ if (_val.uint < 4652218415073722368ull) { \
GRPC_STATS_INC_HISTOGRAM( \
(exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_IOV_SIZE, \
- grpc_stats_table_3[((_hist_idx - 4622945017495814144ull) >> 49)]); \
+ grpc_stats_table_3[((_val.uint - 4622945017495814144ull) >> 49)]); \
} else { \
GRPC_STATS_INC_HISTOGRAM( \
(exec_ctx), GRPC_STATS_HISTOGRAM_TCP_WRITE_IOV_SIZE, \
- grpc_stats_histo_find_bucket_slow((exec_ctx), (value), \
+ grpc_stats_histo_find_bucket_slow((exec_ctx), _val.dbl, \
grpc_stats_table_2, 64)); \
} \
} \
} while (false)
#define GRPC_STATS_INC_TCP_READ_SIZE(exec_ctx, value) \
do { \
- double _hist_val = (double)(value); \
- if (_hist_val < 0) _hist_val = 0; \
- uint64_t _hist_idx = *(uint64_t *)&_hist_val; \
- if (_hist_val < 5.000000) { \
+ union { \
+ double dbl; \
+ uint64_t uint; \
+ } _val; \
+ _val.dbl = (double)(value); \
+ if (_val.dbl < 0) _val.dbl = 0; \
+ if (_val.dbl < 5.000000) { \
GRPC_STATS_INC_HISTOGRAM((exec_ctx), GRPC_STATS_HISTOGRAM_TCP_READ_SIZE, \
- (int)_hist_val); \
+ (int)_val.dbl); \
} else { \
- if (_hist_idx < 4715268809856909312ull) { \
+ if (_val.uint < 4715268809856909312ull) { \
GRPC_STATS_INC_HISTOGRAM( \
(exec_ctx), GRPC_STATS_HISTOGRAM_TCP_READ_SIZE, \
- grpc_stats_table_1[((_hist_idx - 4617315517961601024ull) >> 50)]); \
+ grpc_stats_table_1[((_val.uint - 4617315517961601024ull) >> 50)]); \
} else { \
GRPC_STATS_INC_HISTOGRAM( \
(exec_ctx), GRPC_STATS_HISTOGRAM_TCP_READ_SIZE, \
- grpc_stats_histo_find_bucket_slow((exec_ctx), (value), \
+ grpc_stats_histo_find_bucket_slow((exec_ctx), _val.dbl, \
grpc_stats_table_0, 64)); \
} \
} \
diff --git a/src/core/lib/debug/stats_data.yaml b/src/core/lib/debug/stats_data.yaml
index ded3e89cb2..b8d5f71991 100644
--- a/src/core/lib/debug/stats_data.yaml
+++ b/src/core/lib/debug/stats_data.yaml
@@ -1,10 +1,19 @@
#Stats data declaration
#use tools / codegen / core / gen_stats_data.py to turn this into stats_data.h
-- counter:client_calls_created -
- counter:server_calls_created - counter:syscall_write -
- counter:syscall_read - counter:syscall_poll - counter:syscall_wait -
- counter:histogram_slow_lookups -
- histogram:tcp_write_size max:16777216 #16 meg max write tracked buckets:64 -
- histogram:tcp_write_iov_size max:1024 buckets:64 -
- histogram:tcp_read_size max:16777216 buckets:64
+- counter: client_calls_created
+- counter: server_calls_created
+- counter: syscall_write
+- counter: syscall_read
+- counter: syscall_poll
+- counter: syscall_wait
+- counter: histogram_slow_lookups
+- histogram: tcp_write_size
+ max: 16777216 # 16 meg max write tracked
+ buckets: 64
+- histogram: tcp_write_iov_size
+ max: 1024
+ buckets: 64
+- histogram: tcp_read_size
+ max: 16777216
+ buckets: 64