From: Vladimir Davydov <vdavydov.dev@gmail.com> To: kostja@tarantool.org Cc: tarantool-patches@freelists.org Subject: [PATCH v2 03/11] vinyl: minor refactoring of quota methods Date: Fri, 28 Sep 2018 20:40:01 +0300 [thread overview] Message-ID: <aab16fa614d125d9c8a8c44d490c2e9473e7e683.1538155645.git.vdavydov.dev@gmail.com> (raw) In-Reply-To: <cover.1538155645.git.vdavydov.dev@gmail.com> In-Reply-To: <cover.1538155645.git.vdavydov.dev@gmail.com> The refactoring is targeted at facilitating introduction of rate limiting within the quota class. It moves code blocks around, factors out some blocks in functions, and improves comments. No functional changes. Needed for #1862 --- src/box/vy_quota.c | 131 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 40 deletions(-) diff --git a/src/box/vy_quota.c b/src/box/vy_quota.c index e6d22348..64ce56c0 100644 --- a/src/box/vy_quota.c +++ b/src/box/vy_quota.c @@ -31,6 +31,7 @@ #include "vy_quota.h" #include <assert.h> +#include <stdbool.h> #include <stddef.h> #include <tarantool_ev.h> @@ -40,13 +41,55 @@ #include "trivia/util.h" /** - * Returns true if the quota limit is exceeded and so consumers - * have to wait. + * Return true if the requested amount of memory may be consumed + * right now, false if consumers have to wait. */ static inline bool -vy_quota_is_exceeded(struct vy_quota *q) +vy_quota_may_use(struct vy_quota *q, size_t size) { - return q->used > q->limit; + if (q->used + size > q->limit) + return false; + return true; +} + +/** + * Consume the given amount of memory without checking the limit. + */ +static inline void +vy_quota_do_use(struct vy_quota *q, size_t size) +{ + q->used += size; +} + +/** + * Return the given amount of memory without waking blocked fibers. + * This function is an exact opposite of vy_quota_do_use(). + */ +static inline void +vy_quota_do_unuse(struct vy_quota *q, size_t size) +{ + assert(q->used >= size); + q->used -= size; +} + +/** + * Invoke the registered callback in case memory usage exceeds + * the configured limit. + */ +static inline void +vy_quota_check_limit(struct vy_quota *q) +{ + if (q->used > q->limit) + q->quota_exceeded_cb(q); +} + +/** + * Wake up the first consumer in the line waiting for quota. + */ +static void +vy_quota_signal(struct vy_quota *q) +{ + fiber_cond_signal(&q->cond); } void @@ -70,55 +113,63 @@ void vy_quota_set_limit(struct vy_quota *q, size_t limit) { q->limit = limit; - if (q->used >= limit) - q->quota_exceeded_cb(q); - fiber_cond_signal(&q->cond); + vy_quota_check_limit(q); + vy_quota_signal(q); } void vy_quota_force_use(struct vy_quota *q, size_t size) { - q->used += size; - if (q->used >= q->limit) - q->quota_exceeded_cb(q); + vy_quota_do_use(q, size); + vy_quota_check_limit(q); } void vy_quota_release(struct vy_quota *q, size_t size) { - assert(q->used >= size); - q->used -= size; - fiber_cond_signal(&q->cond); + vy_quota_do_unuse(q, size); + vy_quota_signal(q); } int vy_quota_use(struct vy_quota *q, size_t size, double timeout) { - q->used += size; - if (vy_quota_is_exceeded(q)) { - /* Wait for quota. */ - double start_time = ev_monotonic_now(loop()); - double deadline = start_time + timeout; + if (vy_quota_may_use(q, size)) { + vy_quota_do_use(q, size); + return 0; + } - do { - q->quota_exceeded_cb(q); - q->used -= size; - if (fiber_cond_wait_deadline(&q->cond, deadline) != 0) - return -1; /* timed out */ - q->used += size; - } while (vy_quota_is_exceeded(q)); - - double wait_time = ev_monotonic_now(loop()) - start_time; - if (wait_time > q->too_long_threshold) { - say_warn("waited for %zu bytes of vinyl memory quota " - "for too long: %.3f sec", size, wait_time); - } + /* Wait for quota. */ + double wait_start = ev_monotonic_now(loop()); + double deadline = wait_start + timeout; + + do { /* - * Wake up the next fiber in the line waiting - * for quota. + * If the requested amount of memory cannot be + * consumed due to the configured limit, notify + * the caller before going to sleep so that it + * can start memory reclaim immediately. */ - fiber_cond_signal(&q->cond); + if (q->used + size > q->limit) + q->quota_exceeded_cb(q); + if (fiber_cond_wait_deadline(&q->cond, deadline) != 0) + return -1; /* timed out */ + } while (!vy_quota_may_use(q, size)); + + double wait_time = ev_monotonic_now(loop()) - wait_start; + if (wait_time > q->too_long_threshold) { + say_warn("waited for %zu bytes of vinyl memory quota " + "for too long: %.3f sec", size, wait_time); } + + vy_quota_do_use(q, size); + /* + * Blocked consumers are awaken one by one to preserve + * the order they were put to sleep. It's a responsibility + * of a consumer that managed to acquire the requested + * amount of quota to wake up the next one in the line. + */ + vy_quota_signal(q); return 0; } @@ -126,11 +177,11 @@ void vy_quota_adjust(struct vy_quota *q, size_t reserved, size_t used) { if (reserved > used) { - size_t excess = reserved - used; - assert(q->used >= excess); - q->used -= excess; - fiber_cond_signal(&q->cond); + vy_quota_do_unuse(q, reserved - used); + vy_quota_signal(q); + } + if (reserved < used) { + vy_quota_do_use(q, used - reserved); + vy_quota_check_limit(q); } - if (reserved < used) - vy_quota_force_use(q, used - reserved); } -- 2.11.0
next prev parent reply other threads:[~2018-09-28 17:40 UTC|newest] Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-09-28 17:39 [PATCH v2 00/11] vinyl: transaction throttling infrastructure Vladimir Davydov 2018-09-28 17:39 ` [PATCH v2 01/11] vinyl: add helper to start scheduler and enable quota on startup Vladimir Davydov 2018-09-29 4:37 ` [tarantool-patches] " Konstantin Osipov 2018-09-28 17:40 ` [PATCH v2 02/11] vinyl: factor load regulator out of quota Vladimir Davydov 2018-09-29 5:00 ` [tarantool-patches] " Konstantin Osipov 2018-09-29 11:36 ` Vladimir Davydov [not found] ` <20180929114308.GA19162@chai> 2018-10-01 10:27 ` Vladimir Davydov 2018-10-01 10:31 ` Vladimir Davydov 2018-10-02 18:16 ` [tarantool-patches] " Konstantin Osipov 2018-10-03 8:49 ` Vladimir Davydov 2018-09-28 17:40 ` Vladimir Davydov [this message] 2018-09-29 5:01 ` [tarantool-patches] Re: [PATCH v2 03/11] vinyl: minor refactoring of quota methods Konstantin Osipov 2018-09-28 17:40 ` [PATCH v2 04/11] vinyl: move transaction size sanity check to quota Vladimir Davydov 2018-09-29 5:02 ` [tarantool-patches] " Konstantin Osipov 2018-09-28 17:40 ` [PATCH v2 05/11] vinyl: implement quota wait queue without fiber_cond Vladimir Davydov 2018-09-29 5:05 ` [tarantool-patches] " Konstantin Osipov 2018-09-29 11:44 ` Vladimir Davydov 2018-09-28 17:40 ` [PATCH v2 06/11] vinyl: enable quota upon recovery completion explicitly Vladimir Davydov 2018-09-29 5:06 ` [tarantool-patches] " Konstantin Osipov 2018-09-28 17:40 ` [PATCH v2 07/11] vinyl: zap vy_env::memory, read_threads, and write_threads Vladimir Davydov 2018-09-29 5:06 ` [tarantool-patches] " Konstantin Osipov 2018-09-28 17:40 ` [PATCH v2 08/11] vinyl: do not try to trigger dump in regulator if already in progress Vladimir Davydov 2018-09-28 17:40 ` [PATCH v2 09/11] vinyl: do not account zero dump bandwidth Vladimir Davydov 2018-10-12 13:27 ` Vladimir Davydov 2018-10-16 18:25 ` [tarantool-patches] " Konstantin Osipov 2018-10-17 8:44 ` Vladimir Davydov 2018-10-23 7:02 ` Konstantin Osipov 2018-09-28 17:40 ` [PATCH v2 10/11] vinyl: implement basic transaction throttling Vladimir Davydov 2018-09-28 17:40 ` [PATCH v2 11/11] vinyl: introduce quota consumer priorities Vladimir Davydov 2018-10-06 13:24 ` Konstantin Osipov 2018-10-08 11:10 ` Vladimir Davydov 2018-10-09 13:25 ` Vladimir Davydov 2018-10-11 7:02 ` Konstantin Osipov 2018-10-11 8:29 ` Vladimir Davydov 2018-10-03 9:06 ` [PATCH v2 00/11] vinyl: transaction throttling infrastructure Vladimir Davydov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=aab16fa614d125d9c8a8c44d490c2e9473e7e683.1538155645.git.vdavydov.dev@gmail.com \ --to=vdavydov.dev@gmail.com \ --cc=kostja@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='Re: [PATCH v2 03/11] vinyl: minor refactoring of quota methods' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox