From 40565b4a089f44fdcb16f4ed0080b0ca3755e4aa Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 13 Dec 2022 11:55:14 -0300 Subject: Revamp of GC parameters More uniformity when handling GC parameters + avoid divisions by 100 when applying them. --- lapi.c | 30 +++++++++++++++--------------- lgc.c | 14 +++++--------- lgc.h | 44 ++++++++++++++++++++++++++++++++++---------- llimits.h | 2 +- lstate.c | 8 ++++---- ltests.c | 4 ++-- 6 files changed, 61 insertions(+), 41 deletions(-) diff --git a/lapi.c b/lapi.c index d6d7a8db..8c70bd4c 100644 --- a/lapi.c +++ b/lapi.c @@ -1185,15 +1185,15 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { break; } case LUA_GCSETPAUSE: { - int data = va_arg(argp, int); - res = getgcparam(g->gcpause); - setgcparam(g->gcpause, data); + unsigned int data = va_arg(argp, unsigned int); + res = applygcparam(g, gcpause, 100); + setgcparam(g, gcpause, data); break; } case LUA_GCSETSTEPMUL: { - int data = va_arg(argp, int); - res = getgcparam(g->gcstepmul); - setgcparam(g->gcstepmul, data); + unsigned int data = va_arg(argp, unsigned int); + res = applygcparam(g, gcstepmul, 100); + setgcparam(g, gcstepmul, data); break; } case LUA_GCISRUNNING: { @@ -1201,25 +1201,25 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { break; } case LUA_GCGEN: { - int minormul = va_arg(argp, int); - int majormul = va_arg(argp, int); + unsigned int minormul = va_arg(argp, unsigned int); + unsigned int majormul = va_arg(argp, unsigned int); res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; if (minormul != 0) - g->genminormul = minormul; + setgcparam(g, genminormul, minormul); if (majormul != 0) - setgcparam(g->genmajormul, majormul); + setgcparam(g, genmajormul, majormul); luaC_changemode(L, KGC_GEN); break; } case LUA_GCINC: { - int pause = va_arg(argp, int); - int stepmul = va_arg(argp, int); - int stepsize = va_arg(argp, int); + unsigned int pause = va_arg(argp, unsigned int); + unsigned int stepmul = va_arg(argp, unsigned int); + unsigned int stepsize = va_arg(argp, unsigned int); res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; if (pause != 0) - setgcparam(g->gcpause, pause); + setgcparam(g, gcpause, pause); if (stepmul != 0) - setgcparam(g->gcstepmul, stepmul); + setgcparam(g, gcstepmul, stepmul); if (stepsize != 0) g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize : log2maxs(l_obj); diff --git a/lgc.c b/lgc.c index c2b0535d..90a49091 100644 --- a/lgc.c +++ b/lgc.c @@ -1030,14 +1030,10 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { /* ** Set the "time" to wait before starting a new GC cycle; cycle will ** start when number of objects in use hits the threshold of -** approximately ('marked' * pause / 100). (A direct multiplication -** by 'pause' may overflow, and a direct division by 100 may undeflow -** to zero. So, the division is done in two steps. 8 * 12 is near 100 -** and the division by 8 is cheap.) +** approximately (marked * pause / 100). */ static void setpause (global_State *g) { - unsigned int pause = getgcparam(g->gcpause); - l_obj threshold = g->marked / 8 * pause / 12; + l_obj threshold = applygcparam(g, gcpause, g->marked); l_obj debt = gettotalobjs(g) - threshold; if (debt > 0) debt = 0; luaE_setdebt(g, debt); @@ -1289,7 +1285,7 @@ static void atomic2gen (lua_State *L, global_State *g) { ** total number of objects grows 'genminormul'%. */ static void setminordebt (global_State *g) { - luaE_setdebt(g, -(gettotalobjs(g) / 100) * g->genminormul); + luaE_setdebt(g, -applygcparam(g, genminormul, gettotalobjs(g))); } @@ -1387,7 +1383,7 @@ static void genmajorstep (lua_State *L, global_State *g) { */ static void genstep (lua_State *L, global_State *g) { l_obj majorbase = g->GClastmajor; /* count after last major collection */ - l_obj majorinc = (majorbase / 100) * getgcparam(g->genmajormul); + l_obj majorinc = applygcparam(g, genmajormul, majorbase); if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) { /* do a major collection */ enterinc(g); @@ -1601,7 +1597,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) { */ static void incstep (lua_State *L, global_State *g) { l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; - l_obj work2do = stepsize * getgcparam(g->gcstepmul) / 100; + l_obj work2do = applygcparam(g, gcstepmul, stepsize); do { /* repeat until pause or enough "credit" (negative debt) */ l_obj work = singlestep(L); /* perform one single step */ work2do -= work; diff --git a/lgc.h b/lgc.h index 3c871969..6d82690d 100644 --- a/lgc.h +++ b/lgc.h @@ -8,6 +8,9 @@ #define lgc_h +#include + + #include "lobject.h" #include "lstate.h" @@ -122,20 +125,18 @@ /* Default Values for GC parameters */ -#define LUAI_GENMAJORMUL 100 -#define LUAI_GENMINORMUL 20 + +/* generational */ + +#define LUAI_GENMAJORMUL 100 /* major multiplier */ +#define LUAI_GENMINORMUL 20 /* minor multiplier */ + +/* incremental */ /* wait memory to double before starting new cycle */ #define LUAI_GCPAUSE 200 -/* -** some gc parameters are stored divided by 4 to allow a maximum value -** up to 1023 in a 'lu_byte'. -*/ -#define getgcparam(p) ((p) * 4) -#define setgcparam(p,v) ((p) = (v) / 4) - -#define LUAI_GCMUL 300 +#define LUAI_GCMUL 300 /* step multiplier */ /* how many objects to allocate before next GC step (log2) */ #define LUAI_GCSTEPSIZE 8 /* 256 objects */ @@ -149,6 +150,29 @@ #define GCSTPCLS 4 /* bit true when closing Lua state */ #define gcrunning(g) ((g)->gcstp == 0) +/* +** Macros to set and apply GC parameters. GC parameters are given in +** percentage points, but are stored as lu_byte. To reduce their +** values and avoid repeated divisions by 100, these macros store +** the original parameter multiplied by 2^n and divided by 100. +** To apply them, the value is divided by 2^n (a shift) and then +** multiplied by the stored parameter, yielding +** value / 2^n * (original parameter * 2^n / 100), or approximately +** (value * original parameter / 100). +** +** For most parameters, which are typically larger than 100%, 2^n is +** 16 (2^4), allowing maximum values up to 1599. For the minor +** multiplier, which is typically smaller, 2^n is 64 (2^6) to allow more +** precision. +*/ +#define gcparamshift(p) \ + (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4) + +#define setgcparam(g,p,v) \ + (g->p = (cast_uint(v) << gcparamshift(p)) / 100u) +#define applygcparam(g,p,v) (((v) >> gcparamshift(p)) * g->p) + + /* ** Does one step of collection when debt becomes positive. 'pre'/'pos' diff --git a/llimits.h b/llimits.h index 525b3647..e4948791 100644 --- a/llimits.h +++ b/llimits.h @@ -18,7 +18,7 @@ /* ** 'lu_mem' is an unsigned integer big enough to count the total memory ** used by Lua (in bytes). 'l_obj' is a signed integer big enough to -** count the total number of objects used by Lua. (It is negative due +** count the total number of objects used by Lua. (It is signed due ** to the use of debt in several computations.) Usually, 'size_t' and ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. */ diff --git a/lstate.c b/lstate.c index a4379f93..b9897d96 100644 --- a/lstate.c +++ b/lstate.c @@ -392,11 +392,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->marked = 0; g->GCdebt = 0; setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ - setgcparam(g->gcpause, LUAI_GCPAUSE); - setgcparam(g->gcstepmul, LUAI_GCMUL); + setgcparam(g, gcpause, LUAI_GCPAUSE); + setgcparam(g, gcstepmul, LUAI_GCMUL); g->gcstepsize = LUAI_GCSTEPSIZE; - setgcparam(g->genmajormul, LUAI_GENMAJORMUL); - g->genminormul = LUAI_GENMINORMUL; + setgcparam(g, genmajormul, LUAI_GENMAJORMUL); + setgcparam(g, genminormul, LUAI_GENMINORMUL); for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { /* memory allocation error: free partial state */ diff --git a/ltests.c b/ltests.c index d5d2ae68..e2e0d983 100644 --- a/ltests.c +++ b/ltests.c @@ -1031,8 +1031,8 @@ static int query_inc (lua_State *L) { global_State *g = G(L); lua_pushinteger(L, gettotalobjs(g)); lua_pushinteger(L, g->GCdebt); - lua_pushinteger(L, getgcparam(g->gcpause)); - lua_pushinteger(L, getgcparam(g->gcstepmul)); + lua_pushinteger(L, applygcparam(g, gcpause, 100)); + lua_pushinteger(L, applygcparam(g, gcstepmul, 100)); lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); return 5; } -- cgit v1.2.3-55-g6feb