Browse Source

Revamp of GC parameters

More uniformity when handling GC parameters + avoid divisions by 100
when applying them.
pull/33/head
Roberto Ierusalimschy 2 years ago
parent
commit
40565b4a08
  1. 30
      lapi.c
  2. 14
      lgc.c
  3. 44
      lgc.h
  4. 2
      llimits.h
  5. 8
      lstate.c
  6. 4
      ltests.c

30
lapi.c

@ -1185,15 +1185,15 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
break; break;
} }
case LUA_GCSETPAUSE: { case LUA_GCSETPAUSE: {
int data = va_arg(argp, int); unsigned int data = va_arg(argp, unsigned int);
res = getgcparam(g->gcpause); res = applygcparam(g, gcpause, 100);
setgcparam(g->gcpause, data); setgcparam(g, gcpause, data);
break; break;
} }
case LUA_GCSETSTEPMUL: { case LUA_GCSETSTEPMUL: {
int data = va_arg(argp, int); unsigned int data = va_arg(argp, unsigned int);
res = getgcparam(g->gcstepmul); res = applygcparam(g, gcstepmul, 100);
setgcparam(g->gcstepmul, data); setgcparam(g, gcstepmul, data);
break; break;
} }
case LUA_GCISRUNNING: { case LUA_GCISRUNNING: {
@ -1201,25 +1201,25 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
break; break;
} }
case LUA_GCGEN: { case LUA_GCGEN: {
int minormul = va_arg(argp, int); unsigned int minormul = va_arg(argp, unsigned int);
int majormul = va_arg(argp, int); unsigned int majormul = va_arg(argp, unsigned int);
res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
if (minormul != 0) if (minormul != 0)
g->genminormul = minormul; setgcparam(g, genminormul, minormul);
if (majormul != 0) if (majormul != 0)
setgcparam(g->genmajormul, majormul); setgcparam(g, genmajormul, majormul);
luaC_changemode(L, KGC_GEN); luaC_changemode(L, KGC_GEN);
break; break;
} }
case LUA_GCINC: { case LUA_GCINC: {
int pause = va_arg(argp, int); unsigned int pause = va_arg(argp, unsigned int);
int stepmul = va_arg(argp, int); unsigned int stepmul = va_arg(argp, unsigned int);
int stepsize = va_arg(argp, int); unsigned int stepsize = va_arg(argp, unsigned int);
res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
if (pause != 0) if (pause != 0)
setgcparam(g->gcpause, pause); setgcparam(g, gcpause, pause);
if (stepmul != 0) if (stepmul != 0)
setgcparam(g->gcstepmul, stepmul); setgcparam(g, gcstepmul, stepmul);
if (stepsize != 0) if (stepsize != 0)
g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
: log2maxs(l_obj); : log2maxs(l_obj);

14
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 ** Set the "time" to wait before starting a new GC cycle; cycle will
** start when number of objects in use hits the threshold of ** start when number of objects in use hits the threshold of
** approximately ('marked' * pause / 100). (A direct multiplication ** approximately (marked * pause / 100).
** 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.)
*/ */
static void setpause (global_State *g) { static void setpause (global_State *g) {
unsigned int pause = getgcparam(g->gcpause); l_obj threshold = applygcparam(g, gcpause, g->marked);
l_obj threshold = g->marked / 8 * pause / 12;
l_obj debt = gettotalobjs(g) - threshold; l_obj debt = gettotalobjs(g) - threshold;
if (debt > 0) debt = 0; if (debt > 0) debt = 0;
luaE_setdebt(g, debt); luaE_setdebt(g, debt);
@ -1289,7 +1285,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
** total number of objects grows 'genminormul'%. ** total number of objects grows 'genminormul'%.
*/ */
static void setminordebt (global_State *g) { 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) { static void genstep (lua_State *L, global_State *g) {
l_obj majorbase = g->GClastmajor; /* count after last major collection */ 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) { if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) {
/* do a major collection */ /* do a major collection */
enterinc(g); enterinc(g);
@ -1601,7 +1597,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
*/ */
static void incstep (lua_State *L, global_State *g) { static void incstep (lua_State *L, global_State *g) {
l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 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) */ do { /* repeat until pause or enough "credit" (negative debt) */
l_obj work = singlestep(L); /* perform one single step */ l_obj work = singlestep(L); /* perform one single step */
work2do -= work; work2do -= work;

44
lgc.h

@ -8,6 +8,9 @@
#define lgc_h #define lgc_h
#include <stddef.h>
#include "lobject.h" #include "lobject.h"
#include "lstate.h" #include "lstate.h"
@ -122,20 +125,18 @@
/* Default Values for GC parameters */ /* 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 */ /* wait memory to double before starting new cycle */
#define LUAI_GCPAUSE 200 #define LUAI_GCPAUSE 200
/* #define LUAI_GCMUL 300 /* step multiplier */
** 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
/* how many objects to allocate before next GC step (log2) */ /* how many objects to allocate before next GC step (log2) */
#define LUAI_GCSTEPSIZE 8 /* 256 objects */ #define LUAI_GCSTEPSIZE 8 /* 256 objects */
@ -149,6 +150,29 @@
#define GCSTPCLS 4 /* bit true when closing Lua state */ #define GCSTPCLS 4 /* bit true when closing Lua state */
#define gcrunning(g) ((g)->gcstp == 0) #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' ** Does one step of collection when debt becomes positive. 'pre'/'pos'

2
llimits.h

@ -18,7 +18,7 @@
/* /*
** 'lu_mem' is an unsigned integer big enough to count the total memory ** '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 ** 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 ** to the use of debt in several computations.) Usually, 'size_t' and
** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
*/ */

8
lstate.c

@ -392,11 +392,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->marked = 0; g->marked = 0;
g->GCdebt = 0; g->GCdebt = 0;
setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
setgcparam(g->gcpause, LUAI_GCPAUSE); setgcparam(g, gcpause, LUAI_GCPAUSE);
setgcparam(g->gcstepmul, LUAI_GCMUL); setgcparam(g, gcstepmul, LUAI_GCMUL);
g->gcstepsize = LUAI_GCSTEPSIZE; g->gcstepsize = LUAI_GCSTEPSIZE;
setgcparam(g->genmajormul, LUAI_GENMAJORMUL); setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
g->genminormul = LUAI_GENMINORMUL; setgcparam(g, genminormul, LUAI_GENMINORMUL);
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
/* memory allocation error: free partial state */ /* memory allocation error: free partial state */

4
ltests.c

@ -1031,8 +1031,8 @@ static int query_inc (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
lua_pushinteger(L, gettotalobjs(g)); lua_pushinteger(L, gettotalobjs(g));
lua_pushinteger(L, g->GCdebt); lua_pushinteger(L, g->GCdebt);
lua_pushinteger(L, getgcparam(g->gcpause)); lua_pushinteger(L, applygcparam(g, gcpause, 100));
lua_pushinteger(L, getgcparam(g->gcstepmul)); lua_pushinteger(L, applygcparam(g, gcstepmul, 100));
lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize);
return 5; return 5;
} }

Loading…
Cancel
Save