[PATCH 1/3] vinyl: allow to resize cache online
Vladimir Davydov
vdavydov.dev at gmail.com
Mon Feb 26 20:47:10 MSK 2018
Make box.cfg.vinyl_cache option dynamically configured. If the new
value is less than the current cache usage, it will block until it
reclaims enough cache entries to fit in the new limit.
---
src/box/box.cc | 11 +++++++++-
src/box/box.h | 1 +
src/box/lua/cfg.cc | 12 +++++++++++
src/box/lua/load_cfg.lua | 1 +
src/box/vinyl.c | 14 +++++++++----
src/box/vinyl.h | 12 ++++++++---
src/box/vy_cache.c | 16 ++++++++++++---
src/box/vy_cache.h | 15 +++++++++++---
test/unit/vy_iterators_helper.c | 3 ++-
test/unit/vy_point_lookup.c | 3 ++-
test/vinyl/cache.result | 45 +++++++++++++++++++++++++++++++++++++++++
test/vinyl/cache.test.lua | 17 ++++++++++++++++
12 files changed, 134 insertions(+), 16 deletions(-)
diff --git a/src/box/box.cc b/src/box/box.cc
index 32b08e36..cf7b7ea2 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -742,6 +742,15 @@ box_set_vinyl_max_tuple_size(void)
}
void
+box_set_vinyl_cache(void)
+{
+ struct vinyl_engine *vinyl;
+ vinyl = (struct vinyl_engine *)engine_by_name("vinyl");
+ assert(vinyl != NULL);
+ vinyl_engine_set_cache(vinyl, cfg_geti("vinyl_cache"));
+}
+
+void
box_set_vinyl_timeout(void)
{
struct vinyl_engine *vinyl;
@@ -1539,12 +1548,12 @@ engine_init()
struct vinyl_engine *vinyl;
vinyl = vinyl_engine_new_xc(cfg_gets("vinyl_dir"),
cfg_geti64("vinyl_memory"),
- cfg_geti64("vinyl_cache"),
cfg_geti("vinyl_read_threads"),
cfg_geti("vinyl_write_threads"),
cfg_geti("force_recovery"));
engine_register((struct engine *)vinyl);
box_set_vinyl_max_tuple_size();
+ box_set_vinyl_cache();
box_set_vinyl_timeout();
}
diff --git a/src/box/box.h b/src/box/box.h
index 5c87da9d..baddcf73 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -171,6 +171,7 @@ void box_set_readahead(void);
void box_set_checkpoint_count(void);
void box_set_memtx_max_tuple_size(void);
void box_set_vinyl_max_tuple_size(void);
+void box_set_vinyl_cache(void);
void box_set_vinyl_timeout(void);
void box_set_replication_timeout(void);
void box_set_replication_connect_quorum(void);
diff --git a/src/box/lua/cfg.cc b/src/box/lua/cfg.cc
index be7c4692..5e88ca34 100644
--- a/src/box/lua/cfg.cc
+++ b/src/box/lua/cfg.cc
@@ -199,6 +199,17 @@ lbox_cfg_set_vinyl_max_tuple_size(struct lua_State *L)
}
static int
+lbox_cfg_set_vinyl_cache(struct lua_State *L)
+{
+ try {
+ box_set_vinyl_cache();
+ } catch (Exception *) {
+ luaT_error(L);
+ }
+ return 0;
+}
+
+static int
lbox_cfg_set_vinyl_timeout(struct lua_State *L)
{
try {
@@ -259,6 +270,7 @@ box_lua_cfg_init(struct lua_State *L)
{"cfg_set_read_only", lbox_cfg_set_read_only},
{"cfg_set_memtx_max_tuple_size", lbox_cfg_set_memtx_max_tuple_size},
{"cfg_set_vinyl_max_tuple_size", lbox_cfg_set_vinyl_max_tuple_size},
+ {"cfg_set_vinyl_cache", lbox_cfg_set_vinyl_cache},
{"cfg_set_vinyl_timeout", lbox_cfg_set_vinyl_timeout},
{"cfg_set_replication_timeout", lbox_cfg_set_replication_timeout},
{"cfg_set_replication_connect_quorum",
diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index 891d819d..d4f2128d 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -170,6 +170,7 @@ local dynamic_cfg = {
read_only = private.cfg_set_read_only,
memtx_max_tuple_size = private.cfg_set_memtx_max_tuple_size,
vinyl_max_tuple_size = private.cfg_set_vinyl_max_tuple_size,
+ vinyl_cache = private.cfg_set_vinyl_cache,
vinyl_timeout = private.cfg_set_vinyl_timeout,
checkpoint_count = private.cfg_set_checkpoint_count,
checkpoint_interval = private.checkpoint_daemon.set_checkpoint_interval,
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index df518fcc..03a54670 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -2625,7 +2625,7 @@ vy_squash_schedule(struct vy_index *index, struct tuple *stmt,
void /* struct vy_env */ *arg);
static struct vy_env *
-vy_env_new(const char *path, size_t memory, size_t cache,
+vy_env_new(const char *path, size_t memory,
int read_threads, int write_threads, bool force_recovery)
{
enum { KB = 1000, MB = 1000 * 1000 };
@@ -2700,7 +2700,7 @@ vy_env_new(const char *path, size_t memory, size_t cache,
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);
+ vy_cache_env_create(&e->cache_env, slab_cache);
vy_run_env_create(&e->run_env);
vy_log_init(e->path);
return e;
@@ -2742,7 +2742,7 @@ vy_env_delete(struct vy_env *e)
}
struct vinyl_engine *
-vinyl_engine_new(const char *dir, size_t memory, size_t cache,
+vinyl_engine_new(const char *dir, size_t memory,
int read_threads, int write_threads, bool force_recovery)
{
struct vinyl_engine *vinyl = calloc(1, sizeof(*vinyl));
@@ -2752,7 +2752,7 @@ vinyl_engine_new(const char *dir, size_t memory, size_t cache,
return NULL;
}
- vinyl->env = vy_env_new(dir, memory, cache, read_threads,
+ vinyl->env = vy_env_new(dir, memory, read_threads,
write_threads, force_recovery);
if (vinyl->env == NULL) {
free(vinyl);
@@ -2773,6 +2773,12 @@ vinyl_engine_shutdown(struct engine *engine)
}
void
+vinyl_engine_set_cache(struct vinyl_engine *vinyl, size_t quota)
+{
+ vy_cache_env_set_quota(&vinyl->env->cache_env, quota);
+}
+
+void
vinyl_engine_set_max_tuple_size(struct vinyl_engine *vinyl, size_t max_size)
{
(void)vinyl;
diff --git a/src/box/vinyl.h b/src/box/vinyl.h
index 63add146..ac7afefb 100644
--- a/src/box/vinyl.h
+++ b/src/box/vinyl.h
@@ -42,7 +42,7 @@ struct info_handler;
struct vinyl_engine;
struct vinyl_engine *
-vinyl_engine_new(const char *dir, size_t memory, size_t cache,
+vinyl_engine_new(const char *dir, size_t memory,
int read_threads, int write_threads, bool force_recovery);
/**
@@ -52,6 +52,12 @@ void
vinyl_engine_info(struct vinyl_engine *vinyl, struct info_handler *handler);
/**
+ * Update vinyl cache size.
+ */
+void
+vinyl_engine_set_cache(struct vinyl_engine *vinyl, size_t quota);
+
+/**
* Update max tuple size.
*/
void
@@ -76,11 +82,11 @@ vinyl_engine_set_too_long_threshold(struct vinyl_engine *vinyl,
#include "diag.h"
static inline struct vinyl_engine *
-vinyl_engine_new_xc(const char *dir, size_t memory, size_t cache,
+vinyl_engine_new_xc(const char *dir, size_t memory,
int read_threads, int write_threads, bool force_recovery)
{
struct vinyl_engine *vinyl;
- vinyl = vinyl_engine_new(dir, memory, cache, read_threads,
+ vinyl = vinyl_engine_new(dir, memory, read_threads,
write_threads, force_recovery);
if (vinyl == NULL)
diag_raise();
diff --git a/src/box/vy_cache.c b/src/box/vy_cache.c
index 6bededc1..8a6c53f7 100644
--- a/src/box/vy_cache.c
+++ b/src/box/vy_cache.c
@@ -30,6 +30,7 @@
*/
#include "vy_cache.h"
#include "diag.h"
+#include "fiber.h"
#include "schema_def.h"
#ifndef CT_ASSERT_G
@@ -51,12 +52,11 @@ enum {
};
void
-vy_cache_env_create(struct vy_cache_env *e, struct slab_cache *slab_cache,
- size_t mem_quota)
+vy_cache_env_create(struct vy_cache_env *e, struct slab_cache *slab_cache)
{
rlist_create(&e->cache_lru);
e->mem_used = 0;
- e->mem_quota = mem_quota;
+ e->mem_quota = 0;
mempool_create(&e->cache_entry_mempool, slab_cache,
sizeof(struct vy_cache_entry));
}
@@ -203,6 +203,16 @@ vy_cache_gc(struct vy_cache_env *env)
}
void
+vy_cache_env_set_quota(struct vy_cache_env *env, size_t quota)
+{
+ env->mem_quota = quota;
+ while (env->mem_used > env->mem_quota) {
+ vy_cache_gc(env);
+ fiber_sleep(0);
+ }
+}
+
+void
vy_cache_add(struct vy_cache *cache, struct tuple *stmt,
struct tuple *prev_stmt, const struct tuple *key,
enum iterator_type order)
diff --git a/src/box/vy_cache.h b/src/box/vy_cache.h
index d4e213db..fceda5a2 100644
--- a/src/box/vy_cache.h
+++ b/src/box/vy_cache.h
@@ -127,11 +127,9 @@ struct vy_cache_env {
* Initialize common cache environment.
* @param e - the environment.
* @param slab_cache - source of memory.
- * @param mem_quota - memory limit for the cache.
*/
void
-vy_cache_env_create(struct vy_cache_env *env, struct slab_cache *slab_cache,
- size_t mem_quota);
+vy_cache_env_create(struct vy_cache_env *env, struct slab_cache *slab_cache);
/**
* Destroy and free resources of cache environment.
@@ -141,6 +139,17 @@ void
vy_cache_env_destroy(struct vy_cache_env *e);
/**
+ * Set memory limit for the cache.
+ * @param e - the environment.
+ * @param quota - memory limit for the cache.
+ *
+ * This function blocks until it manages to free enough memory
+ * to fit in the new limit.
+ */
+void
+vy_cache_env_set_quota(struct vy_cache_env *e, size_t quota);
+
+/**
* Tuple cache (of one particular index)
*/
struct vy_cache {
diff --git a/test/unit/vy_iterators_helper.c b/test/unit/vy_iterators_helper.c
index a35f4ef9..0e41de4b 100644
--- a/test/unit/vy_iterators_helper.c
+++ b/test/unit/vy_iterators_helper.c
@@ -19,7 +19,8 @@ vy_iterator_C_test_init(size_t cache_size)
memory_init();
fiber_init(fiber_c_invoke);
tuple_init(NULL);
- vy_cache_env_create(&cache_env, cord_slab_cache(), cache_size);
+ vy_cache_env_create(&cache_env, cord_slab_cache());
+ vy_cache_env_set_quota(&cache_env, cache_size);
vy_key_format = tuple_format_new(&vy_tuple_format_vtab, NULL, 0, 0,
NULL, 0, NULL);
tuple_format_ref(vy_key_format);
diff --git a/test/unit/vy_point_lookup.c b/test/unit/vy_point_lookup.c
index d360b3b4..8217db39 100644
--- a/test/unit/vy_point_lookup.c
+++ b/test/unit/vy_point_lookup.c
@@ -36,7 +36,8 @@ test_basic()
vy_run_env_create(&run_env);
struct vy_cache_env cache_env;
- vy_cache_env_create(&cache_env, slab_cache, QUOTA);
+ vy_cache_env_create(&cache_env, slab_cache);
+ vy_cache_env_set_quota(&cache_env, QUOTA);
struct vy_cache cache;
uint32_t fields[] = { 0 };
diff --git a/test/vinyl/cache.result b/test/vinyl/cache.result
index 117eff05..3ed4d0f9 100644
--- a/test/vinyl/cache.result
+++ b/test/vinyl/cache.result
@@ -1012,3 +1012,48 @@ pk:info().disk.iterator.lookup
s:drop()
---
...
+--
+-- Cache resize
+--
+vinyl_cache = box.cfg.vinyl_cache
+---
+...
+box.cfg{vinyl_cache = 1000 * 1000}
+---
+...
+s = box.schema.space.create('test', {engine = 'vinyl'})
+---
+...
+_ = s:create_index('pk')
+---
+...
+for i = 1, 100 do s:replace{i, string.rep('x', 1000)} end
+---
+...
+for i = 1, 100 do s:get{i} end
+---
+...
+box.info.vinyl().cache.used
+---
+- 107700
+...
+box.cfg{vinyl_cache = 50 * 1000}
+---
+...
+box.info.vinyl().cache.used
+---
+- 49542
+...
+box.cfg{vinyl_cache = 0}
+---
+...
+box.info.vinyl().cache.used
+---
+- 0
+...
+s:drop()
+---
+...
+box.cfg{vinyl_cache = vinyl_cache}
+---
+...
diff --git a/test/vinyl/cache.test.lua b/test/vinyl/cache.test.lua
index 9478a442..40d55abf 100644
--- a/test/vinyl/cache.test.lua
+++ b/test/vinyl/cache.test.lua
@@ -358,3 +358,20 @@ info.lookup
info.get.rows
pk:info().disk.iterator.lookup
s:drop()
+
+--
+-- Cache resize
+--
+vinyl_cache = box.cfg.vinyl_cache
+box.cfg{vinyl_cache = 1000 * 1000}
+s = box.schema.space.create('test', {engine = 'vinyl'})
+_ = s:create_index('pk')
+for i = 1, 100 do s:replace{i, string.rep('x', 1000)} end
+for i = 1, 100 do s:get{i} end
+box.info.vinyl().cache.used
+box.cfg{vinyl_cache = 50 * 1000}
+box.info.vinyl().cache.used
+box.cfg{vinyl_cache = 0}
+box.info.vinyl().cache.used
+s:drop()
+box.cfg{vinyl_cache = vinyl_cache}
--
2.11.0
More information about the Tarantool-patches
mailing list