diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-12-13 11:55:14 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-12-13 11:55:14 -0300 |
| commit | 40565b4a089f44fdcb16f4ed0080b0ca3755e4aa (patch) | |
| tree | d3d692070a250e5756fad95388606736253da8c4 | |
| parent | ff106c028ca944ee5e95b005628e2669b87bcaf2 (diff) | |
| download | lua-40565b4a089f44fdcb16f4ed0080b0ca3755e4aa.tar.gz lua-40565b4a089f44fdcb16f4ed0080b0ca3755e4aa.tar.bz2 lua-40565b4a089f44fdcb16f4ed0080b0ca3755e4aa.zip | |
Revamp of GC parameters
More uniformity when handling GC parameters + avoid divisions by 100
when applying them.
| -rw-r--r-- | lapi.c | 30 | ||||
| -rw-r--r-- | lgc.c | 14 | ||||
| -rw-r--r-- | lgc.h | 44 | ||||
| -rw-r--r-- | llimits.h | 2 | ||||
| -rw-r--r-- | lstate.c | 8 | ||||
| -rw-r--r-- | ltests.c | 4 |
6 files changed, 61 insertions, 41 deletions
| @@ -1185,15 +1185,15 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { | |||
| 1185 | break; | 1185 | break; |
| 1186 | } | 1186 | } |
| 1187 | case LUA_GCSETPAUSE: { | 1187 | case LUA_GCSETPAUSE: { |
| 1188 | int data = va_arg(argp, int); | 1188 | unsigned int data = va_arg(argp, unsigned int); |
| 1189 | res = getgcparam(g->gcpause); | 1189 | res = applygcparam(g, gcpause, 100); |
| 1190 | setgcparam(g->gcpause, data); | 1190 | setgcparam(g, gcpause, data); |
| 1191 | break; | 1191 | break; |
| 1192 | } | 1192 | } |
| 1193 | case LUA_GCSETSTEPMUL: { | 1193 | case LUA_GCSETSTEPMUL: { |
| 1194 | int data = va_arg(argp, int); | 1194 | unsigned int data = va_arg(argp, unsigned int); |
| 1195 | res = getgcparam(g->gcstepmul); | 1195 | res = applygcparam(g, gcstepmul, 100); |
| 1196 | setgcparam(g->gcstepmul, data); | 1196 | setgcparam(g, gcstepmul, data); |
| 1197 | break; | 1197 | break; |
| 1198 | } | 1198 | } |
| 1199 | case LUA_GCISRUNNING: { | 1199 | case LUA_GCISRUNNING: { |
| @@ -1201,25 +1201,25 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { | |||
| 1201 | break; | 1201 | break; |
| 1202 | } | 1202 | } |
| 1203 | case LUA_GCGEN: { | 1203 | case LUA_GCGEN: { |
| 1204 | int minormul = va_arg(argp, int); | 1204 | unsigned int minormul = va_arg(argp, unsigned int); |
| 1205 | int majormul = va_arg(argp, int); | 1205 | unsigned int majormul = va_arg(argp, unsigned int); |
| 1206 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; | 1206 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; |
| 1207 | if (minormul != 0) | 1207 | if (minormul != 0) |
| 1208 | g->genminormul = minormul; | 1208 | setgcparam(g, genminormul, minormul); |
| 1209 | if (majormul != 0) | 1209 | if (majormul != 0) |
| 1210 | setgcparam(g->genmajormul, majormul); | 1210 | setgcparam(g, genmajormul, majormul); |
| 1211 | luaC_changemode(L, KGC_GEN); | 1211 | luaC_changemode(L, KGC_GEN); |
| 1212 | break; | 1212 | break; |
| 1213 | } | 1213 | } |
| 1214 | case LUA_GCINC: { | 1214 | case LUA_GCINC: { |
| 1215 | int pause = va_arg(argp, int); | 1215 | unsigned int pause = va_arg(argp, unsigned int); |
| 1216 | int stepmul = va_arg(argp, int); | 1216 | unsigned int stepmul = va_arg(argp, unsigned int); |
| 1217 | int stepsize = va_arg(argp, int); | 1217 | unsigned int stepsize = va_arg(argp, unsigned int); |
| 1218 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; | 1218 | res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; |
| 1219 | if (pause != 0) | 1219 | if (pause != 0) |
| 1220 | setgcparam(g->gcpause, pause); | 1220 | setgcparam(g, gcpause, pause); |
| 1221 | if (stepmul != 0) | 1221 | if (stepmul != 0) |
| 1222 | setgcparam(g->gcstepmul, stepmul); | 1222 | setgcparam(g, gcstepmul, stepmul); |
| 1223 | if (stepsize != 0) | 1223 | if (stepsize != 0) |
| 1224 | g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize | 1224 | g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize |
| 1225 | : log2maxs(l_obj); | 1225 | : log2maxs(l_obj); |
| @@ -1030,14 +1030,10 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
| 1030 | /* | 1030 | /* |
| 1031 | ** Set the "time" to wait before starting a new GC cycle; cycle will | 1031 | ** Set the "time" to wait before starting a new GC cycle; cycle will |
| 1032 | ** start when number of objects in use hits the threshold of | 1032 | ** start when number of objects in use hits the threshold of |
| 1033 | ** approximately ('marked' * pause / 100). (A direct multiplication | 1033 | ** approximately (marked * pause / 100). |
| 1034 | ** by 'pause' may overflow, and a direct division by 100 may undeflow | ||
| 1035 | ** to zero. So, the division is done in two steps. 8 * 12 is near 100 | ||
| 1036 | ** and the division by 8 is cheap.) | ||
| 1037 | */ | 1034 | */ |
| 1038 | static void setpause (global_State *g) { | 1035 | static void setpause (global_State *g) { |
| 1039 | unsigned int pause = getgcparam(g->gcpause); | 1036 | l_obj threshold = applygcparam(g, gcpause, g->marked); |
| 1040 | l_obj threshold = g->marked / 8 * pause / 12; | ||
| 1041 | l_obj debt = gettotalobjs(g) - threshold; | 1037 | l_obj debt = gettotalobjs(g) - threshold; |
| 1042 | if (debt > 0) debt = 0; | 1038 | if (debt > 0) debt = 0; |
| 1043 | luaE_setdebt(g, debt); | 1039 | luaE_setdebt(g, debt); |
| @@ -1289,7 +1285,7 @@ static void atomic2gen (lua_State *L, global_State *g) { | |||
| 1289 | ** total number of objects grows 'genminormul'%. | 1285 | ** total number of objects grows 'genminormul'%. |
| 1290 | */ | 1286 | */ |
| 1291 | static void setminordebt (global_State *g) { | 1287 | static void setminordebt (global_State *g) { |
| 1292 | luaE_setdebt(g, -(gettotalobjs(g) / 100) * g->genminormul); | 1288 | luaE_setdebt(g, -applygcparam(g, genminormul, gettotalobjs(g))); |
| 1293 | } | 1289 | } |
| 1294 | 1290 | ||
| 1295 | 1291 | ||
| @@ -1387,7 +1383,7 @@ static void genmajorstep (lua_State *L, global_State *g) { | |||
| 1387 | */ | 1383 | */ |
| 1388 | static void genstep (lua_State *L, global_State *g) { | 1384 | static void genstep (lua_State *L, global_State *g) { |
| 1389 | l_obj majorbase = g->GClastmajor; /* count after last major collection */ | 1385 | l_obj majorbase = g->GClastmajor; /* count after last major collection */ |
| 1390 | l_obj majorinc = (majorbase / 100) * getgcparam(g->genmajormul); | 1386 | l_obj majorinc = applygcparam(g, genmajormul, majorbase); |
| 1391 | if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) { | 1387 | if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) { |
| 1392 | /* do a major collection */ | 1388 | /* do a major collection */ |
| 1393 | enterinc(g); | 1389 | enterinc(g); |
| @@ -1601,7 +1597,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) { | |||
| 1601 | */ | 1597 | */ |
| 1602 | static void incstep (lua_State *L, global_State *g) { | 1598 | static void incstep (lua_State *L, global_State *g) { |
| 1603 | l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; | 1599 | l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; |
| 1604 | l_obj work2do = stepsize * getgcparam(g->gcstepmul) / 100; | 1600 | l_obj work2do = applygcparam(g, gcstepmul, stepsize); |
| 1605 | do { /* repeat until pause or enough "credit" (negative debt) */ | 1601 | do { /* repeat until pause or enough "credit" (negative debt) */ |
| 1606 | l_obj work = singlestep(L); /* perform one single step */ | 1602 | l_obj work = singlestep(L); /* perform one single step */ |
| 1607 | work2do -= work; | 1603 | work2do -= work; |
| @@ -8,6 +8,9 @@ | |||
| 8 | #define lgc_h | 8 | #define lgc_h |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | #include <stddef.h> | ||
| 12 | |||
| 13 | |||
| 11 | #include "lobject.h" | 14 | #include "lobject.h" |
| 12 | #include "lstate.h" | 15 | #include "lstate.h" |
| 13 | 16 | ||
| @@ -122,20 +125,18 @@ | |||
| 122 | 125 | ||
| 123 | 126 | ||
| 124 | /* Default Values for GC parameters */ | 127 | /* Default Values for GC parameters */ |
| 125 | #define LUAI_GENMAJORMUL 100 | 128 | |
| 126 | #define LUAI_GENMINORMUL 20 | 129 | /* generational */ |
| 130 | |||
| 131 | #define LUAI_GENMAJORMUL 100 /* major multiplier */ | ||
| 132 | #define LUAI_GENMINORMUL 20 /* minor multiplier */ | ||
| 133 | |||
| 134 | /* incremental */ | ||
| 127 | 135 | ||
| 128 | /* wait memory to double before starting new cycle */ | 136 | /* wait memory to double before starting new cycle */ |
| 129 | #define LUAI_GCPAUSE 200 | 137 | #define LUAI_GCPAUSE 200 |
| 130 | 138 | ||
| 131 | /* | 139 | #define LUAI_GCMUL 300 /* step multiplier */ |
| 132 | ** some gc parameters are stored divided by 4 to allow a maximum value | ||
| 133 | ** up to 1023 in a 'lu_byte'. | ||
| 134 | */ | ||
| 135 | #define getgcparam(p) ((p) * 4) | ||
| 136 | #define setgcparam(p,v) ((p) = (v) / 4) | ||
| 137 | |||
| 138 | #define LUAI_GCMUL 300 | ||
| 139 | 140 | ||
| 140 | /* how many objects to allocate before next GC step (log2) */ | 141 | /* how many objects to allocate before next GC step (log2) */ |
| 141 | #define LUAI_GCSTEPSIZE 8 /* 256 objects */ | 142 | #define LUAI_GCSTEPSIZE 8 /* 256 objects */ |
| @@ -149,6 +150,29 @@ | |||
| 149 | #define GCSTPCLS 4 /* bit true when closing Lua state */ | 150 | #define GCSTPCLS 4 /* bit true when closing Lua state */ |
| 150 | #define gcrunning(g) ((g)->gcstp == 0) | 151 | #define gcrunning(g) ((g)->gcstp == 0) |
| 151 | 152 | ||
| 153 | /* | ||
| 154 | ** Macros to set and apply GC parameters. GC parameters are given in | ||
| 155 | ** percentage points, but are stored as lu_byte. To reduce their | ||
| 156 | ** values and avoid repeated divisions by 100, these macros store | ||
| 157 | ** the original parameter multiplied by 2^n and divided by 100. | ||
| 158 | ** To apply them, the value is divided by 2^n (a shift) and then | ||
| 159 | ** multiplied by the stored parameter, yielding | ||
| 160 | ** value / 2^n * (original parameter * 2^n / 100), or approximately | ||
| 161 | ** (value * original parameter / 100). | ||
| 162 | ** | ||
| 163 | ** For most parameters, which are typically larger than 100%, 2^n is | ||
| 164 | ** 16 (2^4), allowing maximum values up to 1599. For the minor | ||
| 165 | ** multiplier, which is typically smaller, 2^n is 64 (2^6) to allow more | ||
| 166 | ** precision. | ||
| 167 | */ | ||
| 168 | #define gcparamshift(p) \ | ||
| 169 | (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4) | ||
| 170 | |||
| 171 | #define setgcparam(g,p,v) \ | ||
| 172 | (g->p = (cast_uint(v) << gcparamshift(p)) / 100u) | ||
| 173 | #define applygcparam(g,p,v) (((v) >> gcparamshift(p)) * g->p) | ||
| 174 | |||
| 175 | |||
| 152 | 176 | ||
| 153 | /* | 177 | /* |
| 154 | ** Does one step of collection when debt becomes positive. 'pre'/'pos' | 178 | ** Does one step of collection when debt becomes positive. 'pre'/'pos' |
| @@ -18,7 +18,7 @@ | |||
| 18 | /* | 18 | /* |
| 19 | ** 'lu_mem' is an unsigned integer big enough to count the total memory | 19 | ** 'lu_mem' is an unsigned integer big enough to count the total memory |
| 20 | ** used by Lua (in bytes). 'l_obj' is a signed integer big enough to | 20 | ** used by Lua (in bytes). 'l_obj' is a signed integer big enough to |
| 21 | ** count the total number of objects used by Lua. (It is negative due | 21 | ** count the total number of objects used by Lua. (It is signed due |
| 22 | ** to the use of debt in several computations.) Usually, 'size_t' and | 22 | ** to the use of debt in several computations.) Usually, 'size_t' and |
| 23 | ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. | 23 | ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. |
| 24 | */ | 24 | */ |
| @@ -392,11 +392,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 392 | g->marked = 0; | 392 | g->marked = 0; |
| 393 | g->GCdebt = 0; | 393 | g->GCdebt = 0; |
| 394 | setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ | 394 | setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ |
| 395 | setgcparam(g->gcpause, LUAI_GCPAUSE); | 395 | setgcparam(g, gcpause, LUAI_GCPAUSE); |
| 396 | setgcparam(g->gcstepmul, LUAI_GCMUL); | 396 | setgcparam(g, gcstepmul, LUAI_GCMUL); |
| 397 | g->gcstepsize = LUAI_GCSTEPSIZE; | 397 | g->gcstepsize = LUAI_GCSTEPSIZE; |
| 398 | setgcparam(g->genmajormul, LUAI_GENMAJORMUL); | 398 | setgcparam(g, genmajormul, LUAI_GENMAJORMUL); |
| 399 | g->genminormul = LUAI_GENMINORMUL; | 399 | setgcparam(g, genminormul, LUAI_GENMINORMUL); |
| 400 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; | 400 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; |
| 401 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { | 401 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
| 402 | /* memory allocation error: free partial state */ | 402 | /* memory allocation error: free partial state */ |
| @@ -1031,8 +1031,8 @@ static int query_inc (lua_State *L) { | |||
| 1031 | global_State *g = G(L); | 1031 | global_State *g = G(L); |
| 1032 | lua_pushinteger(L, gettotalobjs(g)); | 1032 | lua_pushinteger(L, gettotalobjs(g)); |
| 1033 | lua_pushinteger(L, g->GCdebt); | 1033 | lua_pushinteger(L, g->GCdebt); |
| 1034 | lua_pushinteger(L, getgcparam(g->gcpause)); | 1034 | lua_pushinteger(L, applygcparam(g, gcpause, 100)); |
| 1035 | lua_pushinteger(L, getgcparam(g->gcstepmul)); | 1035 | lua_pushinteger(L, applygcparam(g, gcstepmul, 100)); |
| 1036 | lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); | 1036 | lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize); |
| 1037 | return 5; | 1037 | return 5; |
| 1038 | } | 1038 | } |
