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.
** 'marked' is initialized with the number of fixed objects in the state,
** to count the total number of live objects during a cycle. (That is
** the metafield names, plus the reserved words, plus "_ENV" plus the
** memory-error message.)
** 'GCmarked' is initialized to count the total number of live bytes
** during a cycle.
*/
static void restartcollection (global_State *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;
** 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).
*/
static void setpause (global_State *g) {
@ -1258,7 +1271,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
** in generational mode.
*/
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->reallyold = g->old1 = g->survival = 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:
** 1) Whether the number of added old objects in this collection is more
** than half the number of new objects. ('step' is equal to the debt set
** to trigger the next minor collection; that is equal to the number
** 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'.)
** Decide whether to shift to major mode. It shifts if the accumulated
** number of added old bytes (counted in 'GCmarked') is larger than
** 'minormajor'% of the number of lived bytes after the last major
** collection. (This number is kept in 'GCmajorminor'.)
*/
static int checkminormajor (global_State *g, l_mem addedold1) {
l_mem step = applygcparam(g, MINORMUL, g->GCmajorminor);
static int checkminormajor (global_State *g) {
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);
/* keep total number of added old1 objects */
/* keep total number of added old1 bytes */
g->GCmarked = marked + addedold1;
/* decide whether to shift to major mode */
if (checkminormajor(g, addedold1)) {
if (checkminormajor(g)) {
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
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);
g->gckind = KGC_GENMINOR;
g->GCmajorminor = g->GCmarked; /* "base" for number of objects */
g->GCmarked = 0; /* to count the number of added old1 objects */
g->GCmajorminor = g->GCmarked; /* "base" for number of bytes */
g->GCmarked = 0; /* to count the number of added old1 bytes */
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,
** check whether collector could return to minor collections.
** It checks whether the number of objects 'tobecollected'
** is greater than 'majorminor'% of the number of objects added
** since the last collection ('addedobjs').
** It checks whether the number of bytes 'tobecollected'
** is greater than 'majorminor'% of the number of bytes added
** since the last collection ('addedbytes').
*/
static int checkmajorminor (lua_State *L, global_State *g) {
if (g->gckind == KGC_GENMAJOR) { /* generational mode? */
l_mem numbytes = gettotalbytes(g);
l_mem addedobjs = numbytes - g->GCmajorminor;
l_mem limit = applygcparam(g, MAJORMINOR, addedobjs);
l_mem addedbytes = numbytes - g->GCmajorminor;
l_mem limit = applygcparam(g, MAJORMINOR, addedbytes);
l_mem tobecollected = numbytes - g->GCmarked;
if (tobecollected > limit) {
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 stres;
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 */
//printf("%d-", g->gcstate);
stres = singlestep(L, fast); /* perform one single step */
if (stres == step2minor) /* returned to minor collections? */
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
** 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? */
luaE_setdebt(g, 20000);
else {
//printf("mem: %ld kind: %s ", gettotalbytes(g),
// g->gckind == KGC_INC ? "inc" : g->gckind == KGC_GENMAJOR ? "genmajor" :
// "genminor");
luai_tracegc(L); /* for internal debugging */
switch (g->gckind) {
case KGC_INC: case KGC_GENMAJOR:
incstep(L, g);
//printf("%d) ", g->gcstate);
break;
case KGC_GENMINOR:
youngcollection(L, g);
setminordebt(g);
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,
the collector will do a major collection when the number of old bytes
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.
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.
This option must be followed by one or two extra arguments:
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:
@description{
@item{@St{minormul}| The minor multiplier. }