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.
Diffstat (limited to '')
-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 | } |