From 8e5834b818513d7f84af4dbdc8527782e6959777 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov.dev@gmail.com>
Date: Mon, 19 Jun 2017 16:39:24 +0300
Subject: [PATCH] vinyl: do not (ab)use vy_quota for vy_cache

Using vy_quota, which was implemented to support watermarking,
throttling, timeouts, for accounting cached tuples is an overkill.
Replace it with mem_used and mem_quota counters.
---
 src/box/vinyl.c    |  3 ++-
 src/box/vy_cache.c | 26 +++++++++++++++-----------
 src/box/vy_cache.h |  9 +++++----
 src/box/vy_quota.h | 11 +++++------
 4 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 8d6f30519d..38c125171e 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -36,6 +36,7 @@
 #include "vy_log.h"
 #include "vy_upsert.h"
 #include "vy_write_iterator.h"
+#include "vy_quota.h"
 #include "vy_stat.h"
 
 #define RB_COMPACT 1
@@ -4485,7 +4486,7 @@ vy_info_append_performance(struct vy_env *env, struct info_handler *h)
 	struct vy_cache_env *ce = &env->cache_env;
 	info_table_begin(h, "cache");
 	info_append_int(h, "count", ce->cached_count);
-	info_append_int(h, "used", ce->quota.used);
+	info_append_int(h, "used", ce->mem_used);
 	info_table_end(h);
 
 	info_table_begin(h, "iterator");
diff --git a/src/box/vy_cache.c b/src/box/vy_cache.c
index 48f480ced7..33799a89f9 100644
--- a/src/box/vy_cache.c
+++ b/src/box/vy_cache.c
@@ -51,11 +51,11 @@ enum {
 
 void
 vy_cache_env_create(struct vy_cache_env *e, struct slab_cache *slab_cache,
-		    uint64_t mem_quota)
+		    size_t mem_quota)
 {
 	rlist_create(&e->cache_lru);
-	vy_quota_init(&e->quota, NULL, NULL, NULL);
-	vy_quota_set_limit(&e->quota, mem_quota);
+	e->mem_used = 0;
+	e->mem_quota = mem_quota;
 	mempool_create(&e->cache_entry_mempool, slab_cache,
 		       sizeof(struct vy_cache_entry));
 	e->cached_count = 0;
@@ -67,6 +67,12 @@ vy_cache_env_destroy(struct vy_cache_env *e)
 	mempool_destroy(&e->cache_entry_mempool);
 }
 
+static inline size_t
+vy_cache_entry_size(const struct vy_cache_entry *entry)
+{
+	return sizeof(*entry) + tuple_size(entry->stmt);
+}
+
 static struct vy_cache_entry *
 vy_cache_entry_new(struct vy_cache_env *env, struct vy_cache *cache,
 		   struct tuple *stmt)
@@ -82,8 +88,7 @@ vy_cache_entry_new(struct vy_cache_env *env, struct vy_cache *cache,
 	entry->left_boundary_level = cache->key_def->part_count;
 	entry->right_boundary_level = cache->key_def->part_count;
 	rlist_add(&env->cache_lru, &entry->in_lru);
-	size_t use = sizeof(struct vy_cache_entry) + tuple_size(stmt);
-	vy_quota_force_use(&env->quota, use);
+	env->mem_used += vy_cache_entry_size(entry);
 	env->cached_count++;
 	return entry;
 }
@@ -91,11 +96,11 @@ vy_cache_entry_new(struct vy_cache_env *env, struct vy_cache *cache,
 static void
 vy_cache_entry_delete(struct vy_cache_env *env, struct vy_cache_entry *entry)
 {
-	struct tuple *stmt = entry->stmt;
-	size_t put = sizeof(struct vy_cache_entry) + tuple_size(stmt);
+	assert(env->cached_count > 0);
 	env->cached_count--;
-	vy_quota_release(&env->quota, put);
-	tuple_unref(stmt);
+	assert(env->mem_used >= vy_cache_entry_size(entry));
+	env->mem_used -= vy_cache_entry_size(entry);
+	tuple_unref(entry->stmt);
 	rlist_del(&entry->in_lru);
 	TRASH(entry);
 	mempool_free(&env->cache_entry_mempool, entry);
@@ -190,9 +195,8 @@ vy_cache_gc_step(struct vy_cache_env *env)
 static void
 vy_cache_gc(struct vy_cache_env *env)
 {
-	struct vy_quota *q = &env->quota;
 	for (uint32_t i = 0;
-	     vy_quota_is_exceeded(q) && i < VY_CACHE_CLEANUP_MAX_STEPS;
+	     env->mem_used > env->mem_quota && i < VY_CACHE_CLEANUP_MAX_STEPS;
 	     i++) {
 		vy_cache_gc_step(env);
 	}
diff --git a/src/box/vy_cache.h b/src/box/vy_cache.h
index 0e7792b554..15f7d39842 100644
--- a/src/box/vy_cache.h
+++ b/src/box/vy_cache.h
@@ -39,7 +39,6 @@
 #include "index.h" /* enum iterator_type */
 #include "vy_stmt.h" /* for comparators */
 #include "vy_stmt_iterator.h" /* struct vy_stmt_iterator */
-#include "vy_quota.h"
 #include "small/mempool.h"
 
 #if defined(__cplusplus)
@@ -115,12 +114,14 @@ vy_cache_tree_key_cmp(struct vy_cache_entry *a,
 struct vy_cache_env {
 	/** Common LRU list of read cache. The first element is the newest */
 	struct rlist cache_lru;
-	/** Common quota for read cache */
-	struct vy_quota quota;
 	/** Common mempool for vy_cache_entry struct */
 	struct mempool cache_entry_mempool;
 	/** Number of cached tuples */
 	size_t cached_count;
+	/** Size of memory occupied by cached tuples */
+	size_t mem_used;
+	/** Max memory size that can be used for cache */
+	size_t mem_quota;
 };
 
 /**
@@ -131,7 +132,7 @@ struct vy_cache_env {
  */
 void
 vy_cache_env_create(struct vy_cache_env *env, struct slab_cache *slab_cache,
-		    uint64_t mem_quota);
+		    size_t mem_quota);
 
 /**
  * Destroy and free resources of cache environment.
diff --git a/src/box/vy_quota.h b/src/box/vy_quota.h
index 2eeabd80db..3b187d191f 100644
--- a/src/box/vy_quota.h
+++ b/src/box/vy_quota.h
@@ -120,7 +120,7 @@ static inline void
 vy_quota_set_limit(struct vy_quota *q, size_t limit)
 {
 	q->limit = q->watermark = limit;
-	if (q->quota_exceeded_cb != NULL && q->used >= limit)
+	if (q->used >= limit)
 		q->quota_exceeded_cb(q);
 }
 
@@ -132,7 +132,7 @@ static inline void
 vy_quota_set_watermark(struct vy_quota *q, size_t watermark)
 {
 	q->watermark = watermark;
-	if (q->quota_exceeded_cb != NULL && q->used >= watermark)
+	if (q->used >= watermark)
 		q->quota_exceeded_cb(q);
 }
 
@@ -144,7 +144,7 @@ static inline void
 vy_quota_force_use(struct vy_quota *q, size_t size)
 {
 	q->used += size;
-	if (q->quota_exceeded_cb != NULL && q->used >= q->watermark)
+	if (q->used >= q->watermark)
 		q->quota_exceeded_cb(q);
 }
 
@@ -156,7 +156,7 @@ vy_quota_release(struct vy_quota *q, size_t size)
 {
 	assert(q->used >= size);
 	q->used -= size;
-	if (q->quota_released_cb != NULL && q->used < q->limit)
+	if (q->used < q->limit)
 		q->quota_released_cb(q);
 }
 
@@ -169,8 +169,7 @@ static inline int
 vy_quota_use(struct vy_quota *q, size_t size, ev_tstamp timeout)
 {
 	vy_quota_force_use(q, size);
-	while (q->quota_throttled_cb != NULL &&
-	       q->used >= q->limit && timeout > 0)
+	while (q->used >= q->limit && timeout > 0)
 		timeout = q->quota_throttled_cb(q, timeout);
 	if (q->used > q->limit) {
 		vy_quota_release(q, size);
-- 
GitLab