From 5e28b70a8f4a7f1ebafbd20dadc7be893e2b0660 Mon Sep 17 00:00:00 2001 From: Vladimir Davydov <vdavydov.dev@gmail.com> Date: Wed, 1 Nov 2017 16:47:50 +0300 Subject: [PATCH] vinyl: do not use rmean for calculating quota use rate We have a timer for updating watermark every second. Let's reuse it for quota use rate calculation. This will allow us to get rid of legacy vinyl statistics. Also, let's use EWMA for calculating the average. It is a more efficient and common method, which allows to easily tune the period over which the value is averaged. --- src/box/vinyl.c | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 2f1dceb874..fc2091bee8 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -44,6 +44,7 @@ #include "vy_scheduler.h" #include "vy_stat.h" +#include <math.h> #include <small/lsregion.h> #include <coio_file.h> @@ -100,6 +101,17 @@ struct vy_env { struct vy_quota quota; /** Timer for updating quota watermark. */ ev_timer quota_timer; + /** + * Amount of quota used since the last + * invocation of the quota timer callback. + */ + size_t quota_use_curr; + /** + * Quota use rate, in bytes per second. + * Calculated as exponentially weighted + * moving average of quota_use_curr. + */ + size_t quota_use_rate; /** Common index environment. */ struct vy_index_env index_env; /** Environment for cache subsystem */ @@ -126,6 +138,19 @@ struct vy_env { int write_threads; }; +enum { + /** + * Time interval between successive updates of + * quota watermark and use rate, in seconds. + */ + VY_QUOTA_UPDATE_INTERVAL = 1, + /** + * Period of time over which the quota use rate + * is averaged, in seconds. + */ + VY_QUOTA_RATE_AVG_PERIOD = 5, +}; + /** Mask passed to vy_gc(). */ enum { /** Delete incomplete runs. */ @@ -232,12 +257,6 @@ vy_stat_dump_bandwidth(struct vy_stat *s) return histogram_percentile(s->dump_bw, 10); } -static int64_t -vy_stat_tx_write_rate(struct vy_stat *s) -{ - return rmean_mean(s->rmean, VY_STAT_TX_WRITE); -} - /** Cursor. */ struct vy_cursor { /** @@ -2107,6 +2126,7 @@ vy_prepare(struct vy_env *env, struct vy_tx *tx) rmean_collect(env->stat->rmean, VY_STAT_TX, 1); rmean_collect(env->stat->rmean, VY_STAT_TX_OPS, tx->write_count); rmean_collect(env->stat->rmean, VY_STAT_TX_WRITE, write_size); + env->quota_use_curr += write_size; return 0; } @@ -2179,7 +2199,15 @@ vy_env_quota_timer_cb(ev_loop *loop, ev_timer *timer, int events) struct vy_env *e = timer->data; - int64_t tx_write_rate = vy_stat_tx_write_rate(e->stat); + /* + * Update the quota use rate with the new measurement. + */ + static const double weight = 1 - exp(-VY_QUOTA_UPDATE_INTERVAL / + (double)VY_QUOTA_RATE_AVG_PERIOD); + e->quota_use_rate = (1 - weight) * e->quota_use_rate + + weight * e->quota_use_curr / VY_QUOTA_UPDATE_INTERVAL; + e->quota_use_curr = 0; + int64_t dump_bandwidth = vy_stat_dump_bandwidth(e->stat); /* @@ -2191,10 +2219,10 @@ vy_env_quota_timer_cb(ev_loop *loop, ev_timer *timer, int events) * * limit - watermark watermark * ----------------- = -------------- - * tx_write_rate dump_bandwidth + * quota_use_rate dump_bandwidth */ size_t watermark = ((double)e->quota.limit * dump_bandwidth / - (dump_bandwidth + tx_write_rate + 1)); + (dump_bandwidth + e->quota_use_rate + 1)); vy_quota_set_watermark(&e->quota, watermark); } @@ -2307,7 +2335,8 @@ vy_env_new(const char *path, size_t memory, size_t cache, int read_threads, mempool_create(&e->cursor_pool, slab_cache, sizeof(struct vy_cursor)); vy_quota_create(&e->quota, vy_env_quota_exceeded_cb); - ev_timer_init(&e->quota_timer, vy_env_quota_timer_cb, 0, 1.); + ev_timer_init(&e->quota_timer, vy_env_quota_timer_cb, 0, + VY_QUOTA_UPDATE_INTERVAL); e->quota_timer.data = e; ev_timer_start(loop(), &e->quota_timer); vy_cache_env_create(&e->cache_env, slab_cache, cache); -- GitLab