From d0815046d003f8f24efcdb03d35dd125ddd3b5f9 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 18 Oct 2024 17:10:20 -0300 Subject: [PATCH] Some adjustments in transition minor->major Plus extra comments and other details. --- lgc.c | 78 ++++++++++++++++++++++++++---------------------- manual/manual.of | 5 +++- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/lgc.c b/lgc.c index e154402b..58d0bf7d 100644 --- a/lgc.c +++ b/lgc.c @@ -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); } } diff --git a/manual/manual.of b/manual/manual.of index c93fbfcb..6947b2a0 100644 --- a/manual/manual.of +++ b/manual/manual.of @@ -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. }