diff options
author | Craig Tiller <ctiller@google.com> | 2017-08-31 12:20:04 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2017-08-31 12:20:04 -0700 |
commit | 5489d41c15926abbf12a5b8d27b24d1d605d7f0f (patch) | |
tree | da7b27b1b5389607d2e2119b11fb18c0bf51e4f9 /src | |
parent | 520d76d698f7f03038fd7fcfe1a2129acd0fa948 (diff) |
Expose histograms via microbenchmarks
Diffstat (limited to 'src')
-rw-r--r-- | src/core/lib/debug/stats.c | 67 | ||||
-rw-r--r-- | src/core/lib/debug/stats.h | 8 | ||||
-rw-r--r-- | src/core/lib/debug/stats_data.h | 60 | ||||
-rw-r--r-- | src/core/lib/debug/stats_data.yaml | 23 |
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 |