diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-01-10 14:45:58 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-01-10 14:45:58 -0300 |
| commit | 7827c40c49d841daca2a40463b8a60f9a113f77e (patch) | |
| tree | 28e4d4fe0f6a14a6d16c676153653a054d82dd9c | |
| parent | e7af9cdf0b9fca080e8bb3463e16d60933e786f9 (diff) | |
| download | lua-7827c40c49d841daca2a40463b8a60f9a113f77e.tar.gz lua-7827c40c49d841daca2a40463b8a60f9a113f77e.tar.bz2 lua-7827c40c49d841daca2a40463b8a60f9a113f77e.zip | |
A few more tweaks in the garbage collector
| -rw-r--r-- | config.lua | 4 | ||||
| -rw-r--r-- | lapi.c | 14 | ||||
| -rw-r--r-- | lgc.c | 23 | ||||
| -rw-r--r-- | lgc.h | 2 | ||||
| -rw-r--r-- | manual/manual.of | 4 |
5 files changed, 33 insertions, 14 deletions
diff --git a/config.lua b/config.lua new file mode 100644 index 00000000..14afdc8a --- /dev/null +++ b/config.lua | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | collectgarbage("setparam", "minormul", 25) | ||
| 2 | -- collectgarbage("generational") | ||
| 3 | |||
| 4 | |||
| @@ -53,6 +53,16 @@ const char lua_ident[] = | |||
| 53 | #define isupvalue(i) ((i) < LUA_REGISTRYINDEX) | 53 | #define isupvalue(i) ((i) < LUA_REGISTRYINDEX) |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | /* Advance the garbage collector when creating large objects */ | ||
| 57 | static void advancegc (lua_State *L, size_t delta) { | ||
| 58 | delta >>= 5; /* one object for each 32 bytes (empirical) */ | ||
| 59 | if (delta > 0) { | ||
| 60 | global_State *g = G(L); | ||
| 61 | luaE_setdebt(g, g->GCdebt - delta); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | |||
| 56 | /* | 66 | /* |
| 57 | ** Convert an acceptable index to a pointer to its respective value. | 67 | ** Convert an acceptable index to a pointer to its respective value. |
| 58 | ** Non-valid indices return the special nil value 'G(L)->nilvalue'. | 68 | ** Non-valid indices return the special nil value 'G(L)->nilvalue'. |
| @@ -530,6 +540,7 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { | |||
| 530 | ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); | 540 | ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); |
| 531 | setsvalue2s(L, L->top.p, ts); | 541 | setsvalue2s(L, L->top.p, ts); |
| 532 | api_incr_top(L); | 542 | api_incr_top(L); |
| 543 | advancegc(L, len); | ||
| 533 | luaC_checkGC(L); | 544 | luaC_checkGC(L); |
| 534 | lua_unlock(L); | 545 | lua_unlock(L); |
| 535 | return getstr(ts); | 546 | return getstr(ts); |
| @@ -544,6 +555,8 @@ LUA_API const char *lua_pushextlstring (lua_State *L, | |||
| 544 | ts = luaS_newextlstr (L, s, len, falloc, ud); | 555 | ts = luaS_newextlstr (L, s, len, falloc, ud); |
| 545 | setsvalue2s(L, L->top.p, ts); | 556 | setsvalue2s(L, L->top.p, ts); |
| 546 | api_incr_top(L); | 557 | api_incr_top(L); |
| 558 | if (falloc != NULL) /* non-static string? */ | ||
| 559 | advancegc(L, len); /* count its memory */ | ||
| 547 | luaC_checkGC(L); | 560 | luaC_checkGC(L); |
| 548 | lua_unlock(L); | 561 | lua_unlock(L); |
| 549 | return getstr(ts); | 562 | return getstr(ts); |
| @@ -1336,6 +1349,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { | |||
| 1336 | u = luaS_newudata(L, size, nuvalue); | 1349 | u = luaS_newudata(L, size, nuvalue); |
| 1337 | setuvalue(L, s2v(L->top.p), u); | 1350 | setuvalue(L, s2v(L->top.p), u); |
| 1338 | api_incr_top(L); | 1351 | api_incr_top(L); |
| 1352 | advancegc(L, size); | ||
| 1339 | luaC_checkGC(L); | 1353 | luaC_checkGC(L); |
| 1340 | lua_unlock(L); | 1354 | lua_unlock(L); |
| 1341 | return getudatamem(u); | 1355 | return getudatamem(u); |
| @@ -1052,6 +1052,7 @@ static void setpause (global_State *g) { | |||
| 1052 | l_obj threshold = applygcparam(g, PAUSE, g->marked); | 1052 | l_obj threshold = applygcparam(g, PAUSE, g->marked); |
| 1053 | l_obj debt = threshold - gettotalobjs(g); | 1053 | l_obj debt = threshold - gettotalobjs(g); |
| 1054 | if (debt < 0) debt = 0; | 1054 | if (debt < 0) debt = 0; |
| 1055 | //printf("pause: %ld %ld\n", debt, g->marked); | ||
| 1055 | luaE_setdebt(g, debt); | 1056 | luaE_setdebt(g, debt); |
| 1056 | } | 1057 | } |
| 1057 | 1058 | ||
| @@ -1246,7 +1247,7 @@ static void minor2inc (lua_State *L, global_State *g, int kind) { | |||
| 1246 | /* | 1247 | /* |
| 1247 | ** Decide whether to shift to major mode. It tests two conditions: | 1248 | ** Decide whether to shift to major mode. It tests two conditions: |
| 1248 | ** 1) Whether the number of added old objects in this collection is more | 1249 | ** 1) Whether the number of added old objects in this collection is more |
| 1249 | ** than half the number of new objects. ("step" is the number of objects | 1250 | ** than half the number of new objects. ('step' is the number of objects |
| 1250 | ** created between minor collections. Except for forward barriers, it | 1251 | ** created between minor collections. Except for forward barriers, it |
| 1251 | ** is the maximum number of objects that can become old in each minor | 1252 | ** is the maximum number of objects that can become old in each minor |
| 1252 | ** collection.) | 1253 | ** collection.) |
| @@ -1254,15 +1255,11 @@ static void minor2inc (lua_State *L, global_State *g, int kind) { | |||
| 1254 | ** than 'minormajor'% of the number of lived objects after the last | 1255 | ** than 'minormajor'% of the number of lived objects after the last |
| 1255 | ** major collection. (That percentage is computed in 'limit'.) | 1256 | ** major collection. (That percentage is computed in 'limit'.) |
| 1256 | */ | 1257 | */ |
| 1257 | static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) { | 1258 | static int checkminormajor (global_State *g, l_obj addedold1) { |
| 1258 | l_obj step = applygcparam(g, MINORMUL, g->GCmajorminor); | 1259 | l_obj step = applygcparam(g, MINORMUL, g->GCmajorminor); |
| 1259 | l_obj limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); | 1260 | l_obj limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); |
| 1260 | //printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g)); | 1261 | //printf("-> (%ld) major? marked: %ld limit: %ld step: %ld addedold1: %ld)\n", gettotalobjs(g), g->marked, limit, step, addedold1); |
| 1261 | if (addedold1 >= (step >> 1) || g->marked >= limit) { | 1262 | return (addedold1 >= (step >> 1) || g->marked >= limit); |
| 1262 | minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ | ||
| 1263 | return 1; | ||
| 1264 | } | ||
| 1265 | return 0; /* stay in minor mode */ | ||
| 1266 | } | 1263 | } |
| 1267 | 1264 | ||
| 1268 | /* | 1265 | /* |
| @@ -1309,7 +1306,11 @@ static void youngcollection (lua_State *L, global_State *g) { | |||
| 1309 | g->marked = marked + addedold1; | 1306 | g->marked = marked + addedold1; |
| 1310 | 1307 | ||
| 1311 | /* decide whether to shift to major mode */ | 1308 | /* decide whether to shift to major mode */ |
| 1312 | if (!checkminormajor(L, g, addedold1)) | 1309 | if (checkminormajor(g, addedold1)) { |
| 1310 | minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ | ||
| 1311 | g->marked = 0; /* avoid pause in first major cycle */ | ||
| 1312 | } | ||
| 1313 | else | ||
| 1313 | finishgencycle(L, g); /* still in minor mode; finish it */ | 1314 | finishgencycle(L, g); /* still in minor mode; finish it */ |
| 1314 | } | 1315 | } |
| 1315 | 1316 | ||
| @@ -1401,12 +1402,12 @@ static void fullgen (lua_State *L, global_State *g) { | |||
| 1401 | ** since the last collection ('addedobjs'). | 1402 | ** since the last collection ('addedobjs'). |
| 1402 | */ | 1403 | */ |
| 1403 | static int checkmajorminor (lua_State *L, global_State *g) { | 1404 | static int checkmajorminor (lua_State *L, global_State *g) { |
| 1404 | if (g->gckind == KGC_GENMAJOR) { | 1405 | if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ |
| 1405 | l_obj numobjs = gettotalobjs(g); | 1406 | l_obj numobjs = gettotalobjs(g); |
| 1406 | l_obj addedobjs = numobjs - g->GCmajorminor; | 1407 | l_obj addedobjs = numobjs - g->GCmajorminor; |
| 1407 | l_obj limit = applygcparam(g, MAJORMINOR, addedobjs); | 1408 | l_obj limit = applygcparam(g, MAJORMINOR, addedobjs); |
| 1408 | l_obj tobecollected = numobjs - g->marked; | 1409 | l_obj tobecollected = numobjs - g->marked; |
| 1409 | //printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs); | 1410 | //printf("(%ld) -> minor? tobecollected: %ld limit: %ld\n", numobjs, tobecollected, limit); |
| 1410 | if (tobecollected > limit) { | 1411 | if (tobecollected > limit) { |
| 1411 | atomic2gen(L, g); /* return to generational mode */ | 1412 | atomic2gen(L, g); /* return to generational mode */ |
| 1412 | setminordebt(g); | 1413 | setminordebt(g); |
| @@ -183,7 +183,7 @@ | |||
| 183 | /* incremental */ | 183 | /* incremental */ |
| 184 | 184 | ||
| 185 | /* Number of objects must be LUAI_GCPAUSE% before starting new cycle */ | 185 | /* Number of objects must be LUAI_GCPAUSE% before starting new cycle */ |
| 186 | #define LUAI_GCPAUSE 300 | 186 | #define LUAI_GCPAUSE 200 |
| 187 | 187 | ||
| 188 | /* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects | 188 | /* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects |
| 189 | for each new allocated object.) */ | 189 | for each new allocated object.) */ |
diff --git a/manual/manual.of b/manual/manual.of index 6fd0df6d..ae38d7c6 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -664,7 +664,7 @@ Values equal to or less than 100 mean the collector will not wait to | |||
| 664 | start a new cycle. | 664 | start a new cycle. |
| 665 | A value of 200 means that the collector waits for | 665 | A value of 200 means that the collector waits for |
| 666 | the total number of objects to double before starting a new cycle. | 666 | the total number of objects to double before starting a new cycle. |
| 667 | The default value is 300; the maximum value is 1000. | 667 | The default value is 200. |
| 668 | 668 | ||
| 669 | The garbage-collector step size controls the | 669 | The garbage-collector step size controls the |
| 670 | size of each incremental step, | 670 | size of each incremental step, |
| @@ -681,7 +681,7 @@ in each step, @M{n%} objects for each created object. | |||
| 681 | Larger values make the collector more aggressive. | 681 | Larger values make the collector more aggressive. |
| 682 | Beware that values too small can | 682 | Beware that values too small can |
| 683 | make the collector too slow to ever finish a cycle. | 683 | make the collector too slow to ever finish a cycle. |
| 684 | The default value is 200; the maximum value is 1000. | 684 | The default value is 200. |
| 685 | As a special case, a zero value means unlimited work, | 685 | As a special case, a zero value means unlimited work, |
| 686 | effectively producing a non-incremental, stop-the-world collector. | 686 | effectively producing a non-incremental, stop-the-world collector. |
| 687 | 687 | ||
