Skip to content

Commit

Permalink
Perform GC for the creation, execution, deletion of script
Browse files Browse the repository at this point in the history
  • Loading branch information
sundb committed Jun 27, 2024
1 parent a926713 commit 638077c
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 23 deletions.
14 changes: 13 additions & 1 deletion deps/lua/src/lapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,19 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
return res;
}


LUA_API int lua_gc_step (lua_State *L, int steps) {
int res = 0;
global_State *g;
lua_lock(L);
g = G(L);
g->GCthreshold = g->totalbytes;
luaC_stepgc(L, steps);
if (g->gcstate == GCSpause) { /* end of cycle? */
res = 1; /* signal it */
}
lua_unlock(L);
return res;
}

/*
** miscellaneous functions
Expand Down
21 changes: 21 additions & 0 deletions deps/lua/src/lgc.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,27 @@ void luaC_step (lua_State *L) {
}
}

void luaC_stepgc (lua_State *L, int steps) {
global_State *g = G(L);
g->gcdept += g->totalbytes - g->GCthreshold;
do {
singlestep(L);
if (g->gcstate == GCSpause)
break;
} while (steps-- > 0);
if (g->gcstate != GCSpause) {
if (g->gcdept < GCSTEPSIZE)
g->GCthreshold = g->totalbytes + GCSTEPSIZE;
else {
g->gcdept -= GCSTEPSIZE;
g->GCthreshold = g->totalbytes;
}
}
else {
setthreshold(g);
}
}


void luaC_fullgc (lua_State *L) {
global_State *g = G(L);
Expand Down
1 change: 1 addition & 0 deletions deps/lua/src/lgc.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
LUAI_FUNC void luaC_callGCTM (lua_State *L);
LUAI_FUNC void luaC_freeall (lua_State *L);
LUAI_FUNC void luaC_step (lua_State *L);
LUAI_FUNC void luaC_stepgc (lua_State *L, int steps);
LUAI_FUNC void luaC_fullgc (lua_State *L);
LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
Expand Down
1 change: 1 addition & 0 deletions deps/lua/src/lua.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ LUA_API int (lua_status) (lua_State *L);
#define LUA_GCSETSTEPMUL 7

LUA_API int (lua_gc) (lua_State *L, int what, int data);
LUA_API int (lua_gc_step) (lua_State *L, int steps);


/*
Expand Down
4 changes: 2 additions & 2 deletions src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,7 @@ NULL
addReply(c, shared.ok);
} else if (!strcasecmp(c->argv[1]->ptr,"script") && c->argc == 3) {
if (!strcasecmp(c->argv[2]->ptr,"list")) {
dictIterator *di = dictGetIterator(getLuaScripts());
dictIterator *di = dictGetIterator(evalScriptsDict());
dictEntry *de;
while ((de = dictNext(di)) != NULL) {
luaScript *script = dictGetVal(de);
Expand All @@ -1026,7 +1026,7 @@ NULL
dictReleaseIterator(di);
} else if (sdslen(c->argv[2]->ptr) == 40) {
dictEntry *de;
if ((de = dictFind(getLuaScripts(), c->argv[2]->ptr)) == NULL) {
if ((de = dictFind(evalScriptsDict(), c->argv[2]->ptr)) == NULL) {
addReplyErrorObject(c, shared.noscripterr);
return;
}
Expand Down
23 changes: 21 additions & 2 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ void scriptingReset(int async) {
scriptingInit(0);
}

/* Call the Lua garbage collector from time to time to avoid a
* full cycle performed by Lua, which adds too latency.
*
* The call is performed every LUA_GC_CYCLE_PERIOD executed commands
* (and for LUA_GC_CYCLE_PERIOD collection steps) because calling it
* for every command uses too much CPU. */
#define LUA_GC_CYCLE_PERIOD 50
static inline void scriptingGC(void) {
static long gc_count = 0;
(gc_count)++;
if (gc_count >= LUA_GC_CYCLE_PERIOD) {
lua_gc(lctx.lua, LUA_GCSTEP, LUA_GC_CYCLE_PERIOD);
gc_count = 0;
}
}

/* ---------------------------------------------------------------------------
* EVAL and SCRIPT commands implementation
* ------------------------------------------------------------------------- */
Expand Down Expand Up @@ -457,6 +473,8 @@ sds luaCreateFunction(client *c, robj *body, int evalsha) {
return NULL;
}

scriptingGC();

serverAssert(lua_isfunction(lctx.lua, -1));

lua_setfield(lctx.lua, LUA_REGISTRYINDEX, funcname);
Expand Down Expand Up @@ -600,6 +618,7 @@ void evalGenericCommand(client *c, int evalsha) {
luaCallFunction(&rctx, lua, c->argv+3, numkeys, c->argv+3+numkeys, c->argc-3-numkeys, ldb.active);
lua_pop(lua,1); /* Remove the error handler. */
scriptResetRun(&rctx);
scriptingGC();

if (l->node) {
/* Quick removal and re-insertion after the script is called to
Expand Down Expand Up @@ -1738,6 +1757,6 @@ void luaLdbLineHook(lua_State *lua, lua_Debug *ar) {
}
}

dict *getLuaScripts(void) {
return lctx.lua_scripts;
void luaGC(void) {
lua_gc_step(lctx.lua, 1);
}
13 changes: 13 additions & 0 deletions src/function_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,18 @@ static void luaEngineFreeFunction(void *engine_ctx, void *compiled_function) {
zfree(f_ctx);
}

#define LUA_GC_CYCLE_PERIOD 50
static void luaEnglineGC(void *engine_ctx) {
static long gc_count = 0;
gc_count++;
if (gc_count >= LUA_GC_CYCLE_PERIOD) {
luaEngineCtx *lua_engine_ctx = engine_ctx;
lua_State *lua = lua_engine_ctx->lua;
lua_gc(lua, LUA_GCSTEP, LUA_GC_CYCLE_PERIOD);
gc_count = 0;
}
}

static void luaRegisterFunctionArgsInitialize(registerFunctionArgs *register_f_args,
sds name,
sds desc,
Expand Down Expand Up @@ -480,6 +492,7 @@ int luaEngineInitEngine(void) {
.get_function_memory_overhead = luaEngineFunctionMemoryOverhead,
.get_engine_memory_overhead = luaEngineMemoryOverhead,
.free_function = luaEngineFreeFunction,
.gc = luaEnglineGC,
};
return functionsRegisterEngine(LUA_ENGINE_NAME, lua_engine);
}
2 changes: 2 additions & 0 deletions src/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ static void engineFunctionDispose(dict *d, void *obj) {
}
engine *engine = fi->li->ei->engine;
engine->free_function(engine->engine_ctx, fi->function);
engine->gc(engine->engine_ctx);
zfree(fi);
}

Expand Down Expand Up @@ -969,6 +970,7 @@ sds functionsCreateWithLibraryCtx(sds code, int replace, sds* err, functionsLibC
if (engine->create(engine->engine_ctx, new_li, md.code, timeout, err) != C_OK) {
goto error;
}
engine->gc(engine->engine_ctx);

if (dictSize(new_li->functions) == 0) {
*err = sdsnew("No functions registered");
Expand Down
3 changes: 3 additions & 0 deletions src/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ typedef struct engine {

/* free the given function */
void (*free_function)(void *engine_ctx, void *compiled_function);

/* Perform the garbage collector */
void (*gc)(void *engine_ctx);
} engine;

/* Hold information about an engine.
Expand Down
1 change: 0 additions & 1 deletion src/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ extern scriptFlag scripts_flags_def[];

void luaEnvInit(void);
lua_State *createLuaState(void);
dict *getLuaScripts(void);
uint64_t scriptFlagsToCmdFlags(uint64_t cmd_flags, uint64_t script_flags);
int scriptPrepareForRun(scriptRunCtx *r_ctx, client *engine_client, client *caller, const char *funcname, uint64_t script_flags, int ro);
void scriptResetRun(scriptRunCtx *r_ctx);
Expand Down
17 changes: 0 additions & 17 deletions src/script_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -1650,23 +1650,6 @@ void luaCallFunction(scriptRunCtx* run_ctx, lua_State *lua, robj** keys, size_t
err = lua_pcall(lua,2,1,-4);
}

/* Call the Lua garbage collector from time to time to avoid a
* full cycle performed by Lua, which adds too latency.
*
* The call is performed every LUA_GC_CYCLE_PERIOD executed commands
* (and for LUA_GC_CYCLE_PERIOD collection steps) because calling it
* for every command uses too much CPU. */
#define LUA_GC_CYCLE_PERIOD 50
{
static long gc_count = 0;

gc_count++;
if (gc_count == LUA_GC_CYCLE_PERIOD) {
lua_gc(lua,LUA_GCSTEP,LUA_GC_CYCLE_PERIOD);
gc_count = 0;
}
}

if (err) {
/* Error object is a table of the following format:
* {err='<error msg>', source='<source file>', line=<line>}
Expand Down
4 changes: 4 additions & 0 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
/* Handle background operations on Redis databases. */
databasesCron();

run_with_period(100) {
luaGC();
}

/* Start a scheduled AOF rewrite if this was requested by the user while
* a BGSAVE was in progress. */
if (!hasActiveChildProcess() &&
Expand Down
2 changes: 2 additions & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -3830,6 +3830,8 @@ void *malloc(size_t size) __attribute__ ((deprecated));
void *realloc(void *ptr, size_t size) __attribute__ ((deprecated));
#endif

void luaGC(void);

/* Debugging stuff */
void _serverAssertWithInfo(const client *c, const robj *o, const char *estr, const char *file, int line);
void _serverAssert(const char *estr, const char *file, int line);
Expand Down
16 changes: 16 additions & 0 deletions tests/unit/scripting.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -2383,3 +2383,19 @@ start_server {tags {"scripting"}} {
}
}
}

start_server {tags {"scripting"}} {
test "test" {
set dummy_script "--[string repeat x 40]\nreturn "
set n 150000
for {set i 0} {$i < $n} {incr i} {
set val "$dummy_script[format "%06d" $i]"
r script load $val
}
# Output
# Before this fix: 63539200
# Now: 53990400
# 17% more memory usage
puts [s used_memory_lua]
}
}

0 comments on commit 638077c

Please sign in to comment.