Some adjustments in transition minor->major

Plus extra comments and other details.
This commit is contained in:
Roberto Ierusalimschy 2024-10-18 17:10:20 -03:00
parent 3d54b42d59
commit d0815046d0
2 changed files with 46 additions and 37 deletions

78
lgc.c
View File

@ -424,10 +424,8 @@ static void cleargraylists (global_State *g) {
/* /*
** mark root set and reset all gray lists, to start a new collection. ** mark root set and reset all gray lists, to start a new collection.
** 'marked' is initialized with the number of fixed objects in the state, ** 'GCmarked' is initialized to count the total number of live bytes
** to count the total number of live objects during a cycle. (That is ** during a cycle.
** the metafield names, plus the reserved words, plus "_ENV" plus the
** memory-error message.)
*/ */
static void restartcollection (global_State *g) { static void restartcollection (global_State *g) {
cleargraylists(g); cleargraylists(g);
@ -1067,10 +1065,25 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
** ======================================================= ** =======================================================
*/ */
/*
** Fields 'GCmarked' and 'GCmajorminor' are used to control the pace and
** the mode of the collector. They play several roles, depending on the
** mode of the collector:
** * KGC_INC:
** GCmarked: number of marked bytes during a cycle.
** GCmajorminor: not used.
** * KGC_GENMINOR
** GCmarked: number of bytes that became old since last major collection.
** GCmajorminor: number of bytes marked in last major collection.
** * KGC_GENMAJOR
** GCmarked: number of bytes that became old sinse last major collection.
** GCmajorminor: number of bytes marked in last major collection.
*/
/* /*
** Set the "time" to wait before starting a new incremental cycle; ** Set the "time" to wait before starting a new incremental cycle;
** cycle will start when number of objects in use hits the threshold of ** cycle will start when number of bytes in use hits the threshold of
** approximately (marked * pause / 100). ** approximately (marked * pause / 100).
*/ */
static void setpause (global_State *g) { static void setpause (global_State *g) {
@ -1258,7 +1271,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
** in generational mode. ** in generational mode.
*/ */
static void minor2inc (lua_State *L, global_State *g, lu_byte kind) { static void minor2inc (lua_State *L, global_State *g, lu_byte kind) {
g->GCmajorminor = g->GCmarked; /* number of live objects */ g->GCmajorminor = g->GCmarked; /* number of live bytes */
g->gckind = kind; g->gckind = kind;
g->reallyold = g->old1 = g->survival = NULL; g->reallyold = g->old1 = g->survival = NULL;
g->finobjrold = g->finobjold1 = g->finobjsur = NULL; g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
@ -1269,21 +1282,16 @@ static void minor2inc (lua_State *L, global_State *g, lu_byte kind) {
/* /*
** Decide whether to shift to major mode. It tests two conditions: ** Decide whether to shift to major mode. It shifts if the accumulated
** 1) Whether the number of added old objects in this collection is more ** number of added old bytes (counted in 'GCmarked') is larger than
** than half the number of new objects. ('step' is equal to the debt set ** 'minormajor'% of the number of lived bytes after the last major
** to trigger the next minor collection; that is equal to the number ** collection. (This number is kept in 'GCmajorminor'.)
** of objects created since the previous minor collection. Except for
** forward barriers, it is the maximum number of objects that can become
** old in each minor collection.)
** 2) Whether the accumulated number of added old objects is larger
** than 'minormajor'% of the number of lived objects after the last
** major collection. (That percentage is computed in 'limit'.)
*/ */
static int checkminormajor (global_State *g, l_mem addedold1) { static int checkminormajor (global_State *g) {
l_mem step = applygcparam(g, MINORMUL, g->GCmajorminor);
l_mem limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); l_mem limit = applygcparam(g, MINORMAJOR, g->GCmajorminor);
return (addedold1 >= (step >> 1) || g->GCmarked >= limit); if (limit == 0)
return 0; /* special case: 'minormajor' 0 stops major collections */
return (g->GCmarked >= limit);
} }
/* /*
@ -1326,13 +1334,13 @@ static void youngcollection (lua_State *L, global_State *g) {
sweepgen(L, g, &g->tobefnz, NULL, &dummy, &addedold1); sweepgen(L, g, &g->tobefnz, NULL, &dummy, &addedold1);
/* keep total number of added old1 objects */ /* keep total number of added old1 bytes */
g->GCmarked = marked + addedold1; g->GCmarked = marked + addedold1;
/* decide whether to shift to major mode */ /* decide whether to shift to major mode */
if (checkminormajor(g, addedold1)) { if (checkminormajor(g)) {
minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */
g->GCmarked = 0; /* avoid pause in first major cycle */ g->GCmarked = 0; /* avoid pause in first major cycle (see 'setpause') */
} }
else else
finishgencycle(L, g); /* still in minor mode; finish it */ finishgencycle(L, g); /* still in minor mode; finish it */
@ -1361,8 +1369,8 @@ static void atomic2gen (lua_State *L, global_State *g) {
sweep2old(L, &g->tobefnz); sweep2old(L, &g->tobefnz);
g->gckind = KGC_GENMINOR; g->gckind = KGC_GENMINOR;
g->GCmajorminor = g->GCmarked; /* "base" for number of objects */ g->GCmajorminor = g->GCmarked; /* "base" for number of bytes */
g->GCmarked = 0; /* to count the number of added old1 objects */ g->GCmarked = 0; /* to count the number of added old1 bytes */
finishgencycle(L, g); finishgencycle(L, g);
} }
@ -1423,15 +1431,15 @@ static void fullgen (lua_State *L, global_State *g) {
/* /*
** After an atomic incremental step from a major collection, ** After an atomic incremental step from a major collection,
** check whether collector could return to minor collections. ** check whether collector could return to minor collections.
** It checks whether the number of objects 'tobecollected' ** It checks whether the number of bytes 'tobecollected'
** is greater than 'majorminor'% of the number of objects added ** is greater than 'majorminor'% of the number of bytes added
** since the last collection ('addedobjs'). ** since the last collection ('addedbytes').
*/ */
static int checkmajorminor (lua_State *L, global_State *g) { static int checkmajorminor (lua_State *L, global_State *g) {
if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ if (g->gckind == KGC_GENMAJOR) { /* generational mode? */
l_mem numbytes = gettotalbytes(g); l_mem numbytes = gettotalbytes(g);
l_mem addedobjs = numbytes - g->GCmajorminor; l_mem addedbytes = numbytes - g->GCmajorminor;
l_mem limit = applygcparam(g, MAJORMINOR, addedobjs); l_mem limit = applygcparam(g, MAJORMINOR, addedbytes);
l_mem tobecollected = numbytes - g->GCmarked; l_mem tobecollected = numbytes - g->GCmarked;
if (tobecollected > limit) { if (tobecollected > limit) {
atomic2gen(L, g); /* return to generational mode */ atomic2gen(L, g); /* return to generational mode */
@ -1670,9 +1678,7 @@ static void incstep (lua_State *L, global_State *g) {
l_mem work2do = applygcparam(g, STEPMUL, stepsize); l_mem work2do = applygcparam(g, STEPMUL, stepsize);
l_mem stres; l_mem stres;
int fast = (work2do == 0); /* special case: do a full collection */ int fast = (work2do == 0); /* special case: do a full collection */
//printf("\n** %ld %ld %d\n", work2do, stepsize, g->gcstate);
do { /* repeat until enough work */ do { /* repeat until enough work */
//printf("%d-", g->gcstate);
stres = singlestep(L, fast); /* perform one single step */ stres = singlestep(L, fast); /* perform one single step */
if (stres == step2minor) /* returned to minor collections? */ if (stres == step2minor) /* returned to minor collections? */
return; /* nothing else to be done here */ return; /* nothing else to be done here */
@ -1688,6 +1694,10 @@ static void incstep (lua_State *L, global_State *g) {
} }
#if !defined(luai_tracegc)
#define luai_tracegc(L) ((void)0)
#endif
/* /*
** Performs a basic GC step if collector is running. (If collector is ** Performs a basic GC step if collector is running. (If collector is
** not running, set a reasonable debt to avoid it being called at ** not running, set a reasonable debt to avoid it being called at
@ -1699,20 +1709,16 @@ void luaC_step (lua_State *L) {
if (!gcrunning(g)) /* not running? */ if (!gcrunning(g)) /* not running? */
luaE_setdebt(g, 20000); luaE_setdebt(g, 20000);
else { else {
//printf("mem: %ld kind: %s ", gettotalbytes(g), luai_tracegc(L); /* for internal debugging */
// g->gckind == KGC_INC ? "inc" : g->gckind == KGC_GENMAJOR ? "genmajor" :
// "genminor");
switch (g->gckind) { switch (g->gckind) {
case KGC_INC: case KGC_GENMAJOR: case KGC_INC: case KGC_GENMAJOR:
incstep(L, g); incstep(L, g);
//printf("%d) ", g->gcstate);
break; break;
case KGC_GENMINOR: case KGC_GENMINOR:
youngcollection(L, g); youngcollection(L, g);
setminordebt(g); setminordebt(g);
break; break;
} }
//printf("-> mem: %ld debt: %ld\n", gettotalbytes(g), g->GCdebt);
} }
} }

View File

@ -719,6 +719,8 @@ than the total after the previous major collection.
For instance, for a multiplier of 100, For instance, for a multiplier of 100,
the collector will do a major collection when the number of old bytes the collector will do a major collection when the number of old bytes
gets larger than twice the total after the previous major collection. gets larger than twice the total after the previous major collection.
As a special case,
a value of 0 stops the collector from doing major collections.
The major-minor multiplier controls the shift back to minor collections. The major-minor multiplier controls the shift back to minor collections.
For a multiplier @M{x}, For a multiplier @M{x},
@ -6441,7 +6443,8 @@ Changes the collector mode to generational and returns the previous mode.
Changes and/or retrieves the values of a parameter of the collector. Changes and/or retrieves the values of a parameter of the collector.
This option must be followed by one or two extra arguments: This option must be followed by one or two extra arguments:
The name of the parameter being changed or retrieved (a string) The name of the parameter being changed or retrieved (a string)
and an optional new value for that parameter (an integer). and an optional new value for that parameter,
an integer in the range @M{[0,100000]}.
The first argument must have one of the following values: The first argument must have one of the following values:
@description{ @description{
@item{@St{minormul}| The minor multiplier. } @item{@St{minormul}| The minor multiplier. }