lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 7827c40c49d841daca2a40463b8a60f9a113f77e
parent e7af9cdf0b9fca080e8bb3463e16d60933e786f9
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Wed, 10 Jan 2024 14:45:31 -0300

A few more tweaks in the garbage collector

Diffstat:
Aconfig.lua | 4++++
Mlapi.c | 14++++++++++++++
Mlgc.c | 23++++++++++++-----------
Mlgc.h | 2+-
Mmanual/manual.of | 4++--
5 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/config.lua b/config.lua @@ -0,0 +1,4 @@ +collectgarbage("setparam", "minormul", 25) +-- collectgarbage("generational") + + diff --git a/lapi.c b/lapi.c @@ -53,6 +53,16 @@ const char lua_ident[] = #define isupvalue(i) ((i) < LUA_REGISTRYINDEX) +/* Advance the garbage collector when creating large objects */ +static void advancegc (lua_State *L, size_t delta) { + delta >>= 5; /* one object for each 32 bytes (empirical) */ + if (delta > 0) { + global_State *g = G(L); + luaE_setdebt(g, g->GCdebt - delta); + } +} + + /* ** Convert an acceptable index to a pointer to its respective value. ** Non-valid indices return the special nil value 'G(L)->nilvalue'. @@ -530,6 +540,7 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); setsvalue2s(L, L->top.p, ts); api_incr_top(L); + advancegc(L, len); luaC_checkGC(L); lua_unlock(L); return getstr(ts); @@ -544,6 +555,8 @@ LUA_API const char *lua_pushextlstring (lua_State *L, ts = luaS_newextlstr (L, s, len, falloc, ud); setsvalue2s(L, L->top.p, ts); api_incr_top(L); + if (falloc != NULL) /* non-static string? */ + advancegc(L, len); /* count its memory */ luaC_checkGC(L); lua_unlock(L); return getstr(ts); @@ -1336,6 +1349,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { u = luaS_newudata(L, size, nuvalue); setuvalue(L, s2v(L->top.p), u); api_incr_top(L); + advancegc(L, size); luaC_checkGC(L); lua_unlock(L); return getudatamem(u); diff --git a/lgc.c b/lgc.c @@ -1052,6 +1052,7 @@ static void setpause (global_State *g) { l_obj threshold = applygcparam(g, PAUSE, g->marked); l_obj debt = threshold - gettotalobjs(g); if (debt < 0) debt = 0; +//printf("pause: %ld %ld\n", debt, g->marked); luaE_setdebt(g, debt); } @@ -1246,7 +1247,7 @@ static void minor2inc (lua_State *L, global_State *g, int kind) { /* ** Decide whether to shift to major mode. It tests two conditions: ** 1) Whether the number of added old objects in this collection is more -** than half the number of new objects. ("step" is the number of objects +** than half the number of new objects. ('step' is the number of objects ** created between minor collections. Except for forward barriers, it ** is the maximum number of objects that can become old in each minor ** collection.) @@ -1254,15 +1255,11 @@ static void minor2inc (lua_State *L, global_State *g, int kind) { ** than 'minormajor'% of the number of lived objects after the last ** major collection. (That percentage is computed in 'limit'.) */ -static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) { +static int checkminormajor (global_State *g, l_obj addedold1) { l_obj step = applygcparam(g, MINORMUL, g->GCmajorminor); l_obj limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); -//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g)); - if (addedold1 >= (step >> 1) || g->marked >= limit) { - minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ - return 1; - } - return 0; /* stay in minor mode */ +//printf("-> (%ld) major? marked: %ld limit: %ld step: %ld addedold1: %ld)\n", gettotalobjs(g), g->marked, limit, step, addedold1); + return (addedold1 >= (step >> 1) || g->marked >= limit); } /* @@ -1309,7 +1306,11 @@ static void youngcollection (lua_State *L, global_State *g) { g->marked = marked + addedold1; /* decide whether to shift to major mode */ - if (!checkminormajor(L, g, addedold1)) + if (checkminormajor(g, addedold1)) { + minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ + g->marked = 0; /* avoid pause in first major cycle */ + } + else finishgencycle(L, g); /* still in minor mode; finish it */ } @@ -1401,12 +1402,12 @@ static void fullgen (lua_State *L, global_State *g) { ** since the last collection ('addedobjs'). */ static int checkmajorminor (lua_State *L, global_State *g) { - if (g->gckind == KGC_GENMAJOR) { + if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ l_obj numobjs = gettotalobjs(g); l_obj addedobjs = numobjs - g->GCmajorminor; l_obj limit = applygcparam(g, MAJORMINOR, addedobjs); l_obj tobecollected = numobjs - g->marked; -//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs); +//printf("(%ld) -> minor? tobecollected: %ld limit: %ld\n", numobjs, tobecollected, limit); if (tobecollected > limit) { atomic2gen(L, g); /* return to generational mode */ setminordebt(g); diff --git a/lgc.h b/lgc.h @@ -183,7 +183,7 @@ /* incremental */ /* Number of objects must be LUAI_GCPAUSE% before starting new cycle */ -#define LUAI_GCPAUSE 300 +#define LUAI_GCPAUSE 200 /* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects for each new allocated object.) */ diff --git a/manual/manual.of b/manual/manual.of @@ -664,7 +664,7 @@ Values equal to or less than 100 mean the collector will not wait to start a new cycle. A value of 200 means that the collector waits for the total number of objects to double before starting a new cycle. -The default value is 300; the maximum value is 1000. +The default value is 200. The garbage-collector step size controls the size of each incremental step, @@ -681,7 +681,7 @@ in each step, @M{n%} objects for each created object. Larger values make the collector more aggressive. Beware that values too small can make the collector too slow to ever finish a cycle. -The default value is 200; the maximum value is 1000. +The default value is 200. As a special case, a zero value means unlimited work, effectively producing a non-incremental, stop-the-world collector.