aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lapi.c25
-rw-r--r--lbaselib.c13
-rw-r--r--lgc.c81
-rw-r--r--lgc.h48
-rw-r--r--lstate.c3
-rw-r--r--lstate.h9
-rw-r--r--lua.c2
-rw-r--r--manual/manual.of134
8 files changed, 187 insertions, 128 deletions
diff --git a/lapi.c b/lapi.c
index 71b679aa..374b3872 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1204,26 +1204,29 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
1204 break; 1204 break;
1205 } 1205 }
1206 case LUA_GCGEN: { 1206 case LUA_GCGEN: {
1207 unsigned int minormul = va_arg(argp, unsigned int); 1207 int minormul = va_arg(argp, int);
1208 unsigned int majormul = va_arg(argp, unsigned int); 1208 int minormajor = va_arg(argp, int);
1209 int majorminor = va_arg(argp, int);
1209 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; 1210 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1210 if (minormul != 0) 1211 if (minormul >= 0)
1211 setgcparam(g, genminormul, minormul); 1212 setgcparam(g, genminormul, minormul);
1212 if (majormul != 0) 1213 if (minormajor >= 0)
1213 setgcparam(g, genmajormul, majormul); 1214 setgcparam(g, minormajor, minormajor);
1215 if (majorminor >= 0)
1216 setgcparam(g, majorminor, majorminor);
1214 luaC_changemode(L, KGC_GENMINOR); 1217 luaC_changemode(L, KGC_GENMINOR);
1215 break; 1218 break;
1216 } 1219 }
1217 case LUA_GCINC: { 1220 case LUA_GCINC: {
1218 unsigned int pause = va_arg(argp, unsigned int); 1221 int pause = va_arg(argp, int);
1219 unsigned int stepmul = va_arg(argp, unsigned int); 1222 int stepmul = va_arg(argp, int);
1220 unsigned int stepsize = va_arg(argp, unsigned int); 1223 int stepsize = va_arg(argp, int);
1221 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; 1224 res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
1222 if (pause != 0) 1225 if (pause >= 0)
1223 setgcparam(g, gcpause, pause); 1226 setgcparam(g, gcpause, pause);
1224 if (stepmul != 0) 1227 if (stepmul >= 0)
1225 setgcparam(g, gcstepmul, stepmul); 1228 setgcparam(g, gcstepmul, stepmul);
1226 if (stepsize != 0) 1229 if (stepsize >= 0)
1227 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize 1230 g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
1228 : log2maxs(l_obj); 1231 : log2maxs(l_obj);
1229 luaC_changemode(L, KGC_INC); 1232 luaC_changemode(L, KGC_INC);
diff --git a/lbaselib.c b/lbaselib.c
index 54a6c02d..9ad84dcf 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -224,14 +224,15 @@ static int luaB_collectgarbage (lua_State *L) {
224 return 1; 224 return 1;
225 } 225 }
226 case LUA_GCGEN: { 226 case LUA_GCGEN: {
227 int minormul = (int)luaL_optinteger(L, 2, 0); 227 int minormul = (int)luaL_optinteger(L, 2, -1);
228 int majormul = (int)luaL_optinteger(L, 3, 0); 228 int majorminor = (int)luaL_optinteger(L, 3, -1);
229 return pushmode(L, lua_gc(L, o, minormul, majormul)); 229 int minormajor = (int)luaL_optinteger(L, 4, -1);
230 return pushmode(L, lua_gc(L, o, minormul, majorminor, minormajor));
230 } 231 }
231 case LUA_GCINC: { 232 case LUA_GCINC: {
232 int pause = (int)luaL_optinteger(L, 2, 0); 233 int pause = (int)luaL_optinteger(L, 2, -1);
233 int stepmul = (int)luaL_optinteger(L, 3, 0); 234 int stepmul = (int)luaL_optinteger(L, 3, -1);
234 int stepsize = (int)luaL_optinteger(L, 4, 0); 235 int stepsize = (int)luaL_optinteger(L, 4, -1);
235 return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize)); 236 return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize));
236 } 237 }
237 default: { 238 default: {
diff --git a/lgc.c b/lgc.c
index 50e6e0e9..a4f63765 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1205,20 +1205,21 @@ static void correctgraylists (global_State *g) {
1205/* 1205/*
1206** Mark black 'OLD1' objects when starting a new young collection. 1206** Mark black 'OLD1' objects when starting a new young collection.
1207** Gray objects are already in some gray list, and so will be visited in 1207** Gray objects are already in some gray list, and so will be visited in
1208** the atomic step. The counter 'GCmajorminor' keeps how many objects to 1208** the atomic step. Returns the number of objects that became old.
1209** become old before a major collection.
1210*/ 1209*/
1211static void markold (global_State *g, GCObject *from, GCObject *to) { 1210static l_obj markold (global_State *g, GCObject *from, GCObject *to) {
1212 GCObject *p; 1211 GCObject *p;
1212 l_obj count = 0;
1213 for (p = from; p != to; p = p->next) { 1213 for (p = from; p != to; p = p->next) {
1214 if (getage(p) == G_OLD1) { 1214 if (getage(p) == G_OLD1) {
1215 lua_assert(!iswhite(p)); 1215 lua_assert(!iswhite(p));
1216 setage(p, G_OLD); /* now they are old */ 1216 setage(p, G_OLD); /* now they are old */
1217 g->GCmajorminor--; /* one more old object */ 1217 count++; /* one more old object */
1218 if (isblack(p)) 1218 if (isblack(p))
1219 reallymarkobject(g, p); 1219 reallymarkobject(g, p);
1220 } 1220 }
1221 } 1221 }
1222 return count;
1222} 1223}
1223 1224
1224 1225
@@ -1240,7 +1241,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
1240*/ 1241*/
1241static void atomic2major (lua_State *L, global_State *g) { 1242static void atomic2major (lua_State *L, global_State *g) {
1242 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize; 1243 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1243 g->GCmajorminor = gettotalobjs(g); 1244 g->GCmajorminor = g->marked; /* number of live objects */
1244 g->gckind = KGC_GENMAJOR; 1245 g->gckind = KGC_GENMAJOR;
1245 g->reallyold = g->old1 = g->survival = NULL; 1246 g->reallyold = g->old1 = g->survival = NULL;
1246 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1247 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
@@ -1250,29 +1251,53 @@ static void atomic2major (lua_State *L, global_State *g) {
1250 1251
1251 1252
1252/* 1253/*
1254** Decide whether to shift to major mode. It tests two conditions:
1255** 1) Whether the number of added old objects in this collection is more
1256** than half the number of new objects. ("step" is the number of objects
1257** created between minor collections. Except for forward barriers, it
1258** is the maximum number of objects that can become old in each minor
1259** collection.)
1260** 2) Whether the accumulated number of added old objects is larger
1261** than 'minormajor'% of the number of lived objects after the last
1262** major collection. (That percentage is computed in 'limit'.)
1263*/
1264static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) {
1265 l_obj step = applygcparam(g, genminormul, g->GCmajorminor);
1266 l_obj limit = applygcparam(g, minormajor, g->GCmajorminor);
1267//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g));
1268 if (addedold1 >= (step >> 1) || g->marked >= limit) {
1269 atomic2major(L, g); /* go to major mode */
1270 return 1;
1271 }
1272 return 0; /* stay in minor mode */
1273}
1274
1275/*
1253** Does a young collection. First, mark 'OLD1' objects. Then does the 1276** Does a young collection. First, mark 'OLD1' objects. Then does the
1254** atomic step. Then, check whether to continue in minor mode. If so, 1277** atomic step. Then, check whether to continue in minor mode. If so,
1255** sweep all lists and advance pointers. Finally, finish the collection. 1278** sweep all lists and advance pointers. Finally, finish the collection.
1256*/ 1279*/
1257static void youngcollection (lua_State *L, global_State *g) { 1280static void youngcollection (lua_State *L, global_State *g) {
1281 l_obj addedold1 = 0;
1282 l_obj marked = g->marked; /* preserve 'g->marked' */
1258 GCObject **psurvival; /* to point to first non-dead survival object */ 1283 GCObject **psurvival; /* to point to first non-dead survival object */
1259 GCObject *dummy; /* dummy out parameter to 'sweepgen' */ 1284 GCObject *dummy; /* dummy out parameter to 'sweepgen' */
1260 lua_assert(g->gcstate == GCSpropagate); 1285 lua_assert(g->gcstate == GCSpropagate);
1261 g->marked = 0;
1262 if (g->firstold1) { /* are there regular OLD1 objects? */ 1286 if (g->firstold1) { /* are there regular OLD1 objects? */
1263 markold(g, g->firstold1, g->reallyold); /* mark them */ 1287 addedold1 += markold(g, g->firstold1, g->reallyold); /* mark them */
1264 g->firstold1 = NULL; /* no more OLD1 objects (for now) */ 1288 g->firstold1 = NULL; /* no more OLD1 objects (for now) */
1265 } 1289 }
1266 markold(g, g->finobj, g->finobjrold); 1290 addedold1 += markold(g, g->finobj, g->finobjrold);
1267 markold(g, g->tobefnz, NULL); 1291 addedold1 += markold(g, g->tobefnz, NULL);
1292
1293 atomic(L); /* will lose 'g->marked' */
1268 1294
1269 atomic(L); 1295 /* keep total number of added old1 objects */
1296 g->marked = marked + addedold1;
1270 1297
1271 /* decide whether to shift to major mode */ 1298 /* decide whether to shift to major mode */
1272 if (g->GCmajorminor <= 0) { /* ?? */ 1299 if (checkminormajor(L, g, addedold1))
1273 atomic2major(L, g); /* go to major mode */
1274 return; /* nothing else to be done here */ 1300 return; /* nothing else to be done here */
1275 }
1276 1301
1277 /* sweep nursery and get a pointer to its last live element */ 1302 /* sweep nursery and get a pointer to its last live element */
1278 g->gcstate = GCSswpallgc; 1303 g->gcstate = GCSswpallgc;
@@ -1319,7 +1344,8 @@ static void atomic2gen (lua_State *L, global_State *g) {
1319 sweep2old(L, &g->tobefnz); 1344 sweep2old(L, &g->tobefnz);
1320 1345
1321 g->gckind = KGC_GENMINOR; 1346 g->gckind = KGC_GENMINOR;
1322 g->GCmajorminor = applygcparam(g, genmajormul, g->marked); 1347 g->GCmajorminor = g->marked; /* "base" for number of objects */
1348 g->marked = 0; /* to count the number of added old1 objects */
1323 finishgencycle(L, g); 1349 finishgencycle(L, g);
1324} 1350}
1325 1351
@@ -1329,7 +1355,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
1329** total number of objects grows 'genminormul'%. 1355** total number of objects grows 'genminormul'%.
1330*/ 1356*/
1331static void setminordebt (global_State *g) { 1357static void setminordebt (global_State *g) {
1332 luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g))); 1358 luaE_setdebt(g, applygcparam(g, genminormul, g->GCmajorminor));
1333} 1359}
1334 1360
1335 1361
@@ -1369,13 +1395,11 @@ static void enterinc (global_State *g) {
1369*/ 1395*/
1370void luaC_changemode (lua_State *L, int newmode) { 1396void luaC_changemode (lua_State *L, int newmode) {
1371 global_State *g = G(L); 1397 global_State *g = G(L);
1398 if (g->gckind == KGC_GENMAJOR) /* doing major collections? */
1399 g->gckind = KGC_INC; /* already incremental but in name */
1372 if (newmode != g->gckind) { /* does it need to change? */ 1400 if (newmode != g->gckind) { /* does it need to change? */
1373 if (newmode == KGC_INC) { /* entering incremental mode? */ 1401 if (newmode == KGC_INC) /* entering incremental mode? */
1374 if (g->gckind == KGC_GENMAJOR) 1402 enterinc(g); /* entering incremental mode */
1375 g->gckind = KGC_INC; /* already incremental but in name */
1376 else
1377 enterinc(g); /* entering incremental mode */
1378 }
1379 else { 1403 else {
1380 lua_assert(newmode == KGC_GENMINOR); 1404 lua_assert(newmode == KGC_GENMINOR);
1381 entergen(L, g); 1405 entergen(L, g);
@@ -1396,16 +1420,24 @@ static void fullgen (lua_State *L, global_State *g) {
1396/* 1420/*
1397** After an atomic incremental step from a major collection, 1421** After an atomic incremental step from a major collection,
1398** check whether collector could return to minor collections. 1422** check whether collector could return to minor collections.
1423** It checks whether the number of objects 'tobecollected'
1424** is greater than 'majorminor'% of the number of objects added
1425** since the last collection ('addedobjs').
1399*/ 1426*/
1400static int checkmajorminor (lua_State *L, global_State *g) { 1427static int checkmajorminor (lua_State *L, global_State *g) {
1401 if (g->gckind == KGC_GENMAJOR) { 1428 if (g->gckind == KGC_GENMAJOR) {
1402 l_obj numobjs = gettotalobjs(g); /* current count */ 1429 l_obj numobjs = gettotalobjs(g);
1403 if (g->marked < numobjs - (numobjs >> 2)) { /* ?? */ 1430 l_obj addedobjs = numobjs - g->GCmajorminor;
1431 l_obj limit = applygcparam(g, majorminor, addedobjs);
1432 l_obj tobecollected = numobjs - g->marked;
1433//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs);
1434 if (tobecollected > limit) {
1404 atomic2gen(L, g); /* return to generational mode */ 1435 atomic2gen(L, g); /* return to generational mode */
1405 setminordebt(g); 1436 setminordebt(g);
1406 return 0; /* exit incremental collection */ 1437 return 0; /* exit incremental collection */
1407 } 1438 }
1408 } 1439 }
1440 g->GCmajorminor = g->marked; /* prepare for next collection */
1409 return 1; /* stay doing incremental collections */ 1441 return 1; /* stay doing incremental collections */
1410} 1442}
1411 1443
@@ -1634,8 +1666,6 @@ void luaC_step (lua_State *L) {
1634 if (!gcrunning(g)) /* not running? */ 1666 if (!gcrunning(g)) /* not running? */
1635 luaE_setdebt(g, 2000); 1667 luaE_setdebt(g, 2000);
1636 else { 1668 else {
1637//printf("> step: %d %d %ld %ld -> ", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt);
1638
1639 switch (g->gckind) { 1669 switch (g->gckind) {
1640 case KGC_INC: case KGC_GENMAJOR: 1670 case KGC_INC: case KGC_GENMAJOR:
1641 incstep(L, g); 1671 incstep(L, g);
@@ -1645,7 +1675,6 @@ void luaC_step (lua_State *L) {
1645 setminordebt(g); 1675 setminordebt(g);
1646 break; 1676 break;
1647 } 1677 }
1648//printf("%d %d %ld %ld\n", g->gckind, g->gcstate, gettotalobjs(g), g->GCdebt);
1649 } 1678 }
1650} 1679}
1651 1680
diff --git a/lgc.h b/lgc.h
index 3cc0c80d..4cbc6e61 100644
--- a/lgc.h
+++ b/lgc.h
@@ -161,10 +161,24 @@
161 161
162/* Default Values for GC parameters */ 162/* Default Values for GC parameters */
163 163
164/* generational */ 164/*
165** Minor collections will shift to major ones after LUAI_MINORMAJOR%
166** objects become old.
167*/
168#define LUAI_MINORMAJOR 100
169
170/*
171** Major collections will shift to minor ones after a collection
172** collects at least LUAI_MAJORMINOR% of the new objects.
173*/
174#define LUAI_MAJORMINOR 80
175
176/*
177** A young (minor) collection will run after creating LUAI_GENMINORMUL%
178** new objects.
179*/
180#define LUAI_GENMINORMUL 20
165 181
166#define LUAI_GENMAJORMUL 100 /* major multiplier */
167#define LUAI_GENMINORMUL 20 /* minor multiplier */
168 182
169/* incremental */ 183/* incremental */
170 184
@@ -187,27 +201,17 @@
187 201
188/* 202/*
189** Macros to set and apply GC parameters. GC parameters are given in 203** Macros to set and apply GC parameters. GC parameters are given in
190** percentage points, but are stored as lu_byte. To reduce their 204** percentage points, but are stored as lu_byte. To avoid repeated
191** values and avoid repeated divisions by 100, these macros store 205** divisions by 100, these macros store the original parameter
192** the original parameter multiplied by 2^n and divided by 100. 206** multiplied by 128 and divided by 100. To apply them, if it first
193** To apply them, the value is divided by 2^n (a shift) and then 207** divides the value by 128 it may lose precision; if it first
194** multiplied by the stored parameter, yielding 208** multiplies by the parameter, it may overflow. So, it first divides
195** value / 2^n * (original parameter * 2^n / 100), or approximately 209** by 32, then multiply by the parameter, and then divides the result by
196** (value * original parameter / 100). 210** 4.
197**
198** For most parameters, which are typically larger than 100%, 2^n is
199** 16 (2^4), allowing maximum values up to ~1500%, with a granularity
200** of ~6%. For the minor multiplier, which is typically smaller,
201** 2^n is 64 (2^6) to allow more precision. In that case, the maximum
202** value is ~400%, with a granularity of ~1.5%.
203*/ 211*/
204#define gcparamshift(p) \
205 (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4)
206
207#define setgcparam(g,p,v) \
208 (g->p = (cast_uint(v) << gcparamshift(p)) / 100u)
209#define applygcparam(g,p,v) (((v) >> gcparamshift(p)) * g->p)
210 212
213#define setgcparam(g,p,v) (g->gcp##p = (cast_uint(v) << 7) / 100u)
214#define applygcparam(g,p,v) ((((v) >> 5) * g->gcp##p) >> 2)
211 215
212 216
213/* 217/*
diff --git a/lstate.c b/lstate.c
index 1216db35..aab90e34 100644
--- a/lstate.c
+++ b/lstate.c
@@ -368,8 +368,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
368 setgcparam(g, gcpause, LUAI_GCPAUSE); 368 setgcparam(g, gcpause, LUAI_GCPAUSE);
369 setgcparam(g, gcstepmul, LUAI_GCMUL); 369 setgcparam(g, gcstepmul, LUAI_GCMUL);
370 g->gcstepsize = LUAI_GCSTEPSIZE; 370 g->gcstepsize = LUAI_GCSTEPSIZE;
371 setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
372 setgcparam(g, genminormul, LUAI_GENMINORMUL); 371 setgcparam(g, genminormul, LUAI_GENMINORMUL);
372 setgcparam(g, minormajor, LUAI_MINORMAJOR);
373 setgcparam(g, majorminor, LUAI_MAJORMINOR);
373 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 374 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
374 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 375 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
375 /* memory allocation error: free partial state */ 376 /* memory allocation error: free partial state */
diff --git a/lstate.h b/lstate.h
index 1868981b..49acfb7e 100644
--- a/lstate.h
+++ b/lstate.h
@@ -264,16 +264,17 @@ typedef struct global_State {
264 TValue l_registry; 264 TValue l_registry;
265 TValue nilvalue; /* a nil value */ 265 TValue nilvalue; /* a nil value */
266 unsigned int seed; /* randomized seed for hashes */ 266 unsigned int seed; /* randomized seed for hashes */
267 unsigned short gcpgenminormul; /* control minor generational collections */
268 unsigned short gcpmajorminor; /* control shift major->minor */
269 unsigned short gcpminormajor; /* control shift minor->major */
270 unsigned short gcpgcpause; /* size of pause between successive GCs */
271 unsigned short gcpgcstepmul; /* GC "speed" */
267 lu_byte currentwhite; 272 lu_byte currentwhite;
268 lu_byte gcstate; /* state of garbage collector */ 273 lu_byte gcstate; /* state of garbage collector */
269 lu_byte gckind; /* kind of GC running */ 274 lu_byte gckind; /* kind of GC running */
270 lu_byte gcstopem; /* stops emergency collections */ 275 lu_byte gcstopem; /* stops emergency collections */
271 lu_byte genminormul; /* control for minor generational collections */
272 lu_byte genmajormul; /* control for major generational collections */
273 lu_byte gcstp; /* control whether GC is running */ 276 lu_byte gcstp; /* control whether GC is running */
274 lu_byte gcemergency; /* true if this is an emergency collection */ 277 lu_byte gcemergency; /* true if this is an emergency collection */
275 lu_byte gcpause; /* size of pause between successive GCs */
276 lu_byte gcstepmul; /* GC "speed" */
277 lu_byte gcstepsize; /* (log2 of) GC granularity */ 278 lu_byte gcstepsize; /* (log2 of) GC granularity */
278 GCObject *allgc; /* list of all collectable objects */ 279 GCObject *allgc; /* list of all collectable objects */
279 GCObject **sweepgc; /* current position of sweep in list */ 280 GCObject **sweepgc; /* current position of sweep in list */
diff --git a/lua.c b/lua.c
index 1e884b07..d26dd8ac 100644
--- a/lua.c
+++ b/lua.c
@@ -646,7 +646,7 @@ static int pmain (lua_State *L) {
646 luai_openlibs(L); /* open standard libraries */ 646 luai_openlibs(L); /* open standard libraries */
647 createargtable(L, argv, argc, script); /* create table 'arg' */ 647 createargtable(L, argv, argc, script); /* create table 'arg' */
648 lua_gc(L, LUA_GCRESTART); /* start GC... */ 648 lua_gc(L, LUA_GCRESTART); /* start GC... */
649 lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ 649 lua_gc(L, LUA_GCGEN, -1, -1, -1); /* ...in generational mode */
650 if (!(args & has_E)) { /* no option '-E'? */ 650 if (!(args & has_E)) { /* no option '-E'? */
651 if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ 651 if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
652 return 0; /* error running LUA_INIT */ 652 return 0; /* error running LUA_INIT */
diff --git a/manual/manual.of b/manual/manual.of
index 263ced72..8607e57d 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -621,7 +621,8 @@ that is inaccessible from Lua.
621another live object refer to the object.) 621another live object refer to the object.)
622Because Lua has no knowledge about @N{C code}, 622Because Lua has no knowledge about @N{C code},
623it never collects objects accessible through the registry @see{registry}, 623it never collects objects accessible through the registry @see{registry},
624which includes the global environment @see{globalenv}. 624which includes the global environment @see{globalenv} and
625the main thread.
625 626
626 627
627The garbage collector (GC) in Lua can work in two modes: 628The garbage collector (GC) in Lua can work in two modes:
@@ -638,8 +639,8 @@ therefore, optimal settings are also non-portable.
638You can change the GC mode and parameters by calling 639You can change the GC mode and parameters by calling
639@Lid{lua_gc} @N{in C} 640@Lid{lua_gc} @N{in C}
640or @Lid{collectgarbage} in Lua. 641or @Lid{collectgarbage} in Lua.
641You can also use these functions to control 642You can also use these functions to control the collector directly,
642the collector directly (e.g., to stop and restart it). 643for instance to stop or restart it.
643 644
644} 645}
645 646
@@ -656,39 +657,36 @@ and the @def{garbage-collector step size}.
656 657
657The garbage-collector pause 658The garbage-collector pause
658controls how long the collector waits before starting a new cycle. 659controls how long the collector waits before starting a new cycle.
659The collector starts a new cycle when the use of memory 660The collector starts a new cycle when the number of objects
660hits @M{n%} of the use after the previous collection. 661hits @M{n%} of the total after the previous collection.
661Larger values make the collector less aggressive. 662Larger values make the collector less aggressive.
662Values equal to or less than 100 mean the collector will not wait to 663Values equal to or less than 100 mean the collector will not wait to
663start a new cycle. 664start a new cycle.
664A value of 200 means that the collector waits for the total memory in use 665A value of 200 means that the collector waits for
665to double before starting a new cycle. 666the total number of objects to double before starting a new cycle.
666The default value is 200; the maximum value is 1000. 667The default value is 200; the maximum value is 1000.
667 668
668The garbage-collector step multiplier 669The garbage-collector step multiplier
669controls the speed of the collector relative to 670controls the speed of the collector relative to
670memory allocation, 671object creation,
671that is, 672that is,
672how many elements it marks or sweeps for each 673how many objects it marks or sweeps for each object created.
673kilobyte of memory allocated. 674Larger values make the collector more aggressive.
674Larger values make the collector more aggressive but also increase 675Beware that values too small can
675the size of each incremental step. 676make the collector too slow to ever finish a cycle.
676You should not use values less than 100, 677The default value is 300; the maximum value is 1000.
677because they make the collector too slow and
678can result in the collector never finishing a cycle.
679The default value is 100; the maximum value is 1000.
680 678
681The garbage-collector step size controls the 679The garbage-collector step size controls the
682size of each incremental step, 680size of each incremental step,
683specifically how many bytes the interpreter allocates 681specifically how many objects the interpreter creates
684before performing a step. 682before performing a step.
685This parameter is logarithmic: 683This parameter is logarithmic:
686A value of @M{n} means the interpreter will allocate @M{2@sp{n}} 684A value of @M{n} means the interpreter will create @M{2@sp{n}}
687bytes between steps and perform equivalent work during the step. 685objects between steps and perform equivalent work during the step.
688A large value (e.g., 60) makes the collector a stop-the-world 686A large value (e.g., 60) makes the collector a stop-the-world
689(non-incremental) collector. 687(non-incremental) collector.
690The default value is 13, 688The default value is 8,
691which means steps of approximately @N{8 Kbytes}. 689which means steps of approximately @N{256 objects}.
692 690
693} 691}
694 692
@@ -697,31 +695,44 @@ which means steps of approximately @N{8 Kbytes}.
697In generational mode, 695In generational mode,
698the collector does frequent @emph{minor} collections, 696the collector does frequent @emph{minor} collections,
699which traverses only objects recently created. 697which traverses only objects recently created.
700If after a minor collection the use of memory is still above a limit, 698If after a minor collection the number of objects is above a limit,
701the collector does a stop-the-world @emph{major} collection, 699the collector shifts to a @emph{major} collection,
702which traverses all objects. 700which traverses all objects.
703The generational mode uses two parameters: 701The collector will then stay doing major collections until
704the @def{minor multiplier} and the @def{the major multiplier}. 702it detects that the program is generating enough garbage to justify
703going back to minor collections.
704
705The generational mode uses three parameters:
706the @def{minor multiplier}, the @def{minor-major multiplier},
707and the @def{major-minor multiplier}.
705 708
706The minor multiplier controls the frequency of minor collections. 709The minor multiplier controls the frequency of minor collections.
707For a minor multiplier @M{x}, 710For a minor multiplier @M{x},
708a new minor collection will be done when memory 711a new minor collection will be done when the number of objects
709grows @M{x%} larger than the memory in use after the previous major 712grows @M{x%} larger than the number in use just after the last collection.
710collection.
711For instance, for a multiplier of 20, 713For instance, for a multiplier of 20,
712the collector will do a minor collection when the use of memory 714the collector will do a minor collection when the number of objects
713gets 20% larger than the use after the previous major collection. 715gets 20% larger than the total after the last major collection.
714The default value is 20; the maximum value is 200. 716The default value is 20.
715 717
716The major multiplier controls the frequency of major collections. 718The minor-major multiplier controls the shift to major collections.
717For a major multiplier @M{x}, 719For a multiplier @M{x},
718a new major collection will be done when memory 720the collector will shift to a major collection
719grows @M{x%} larger than the memory in use after the previous major 721when the number of old objects grows @M{x%} larger
720collection. 722than the total after the previous major collection.
721For instance, for a multiplier of 100, 723For instance, for a multiplier of 100,
722the collector will do a major collection when the use of memory 724the collector will do a major collection when the number of old objects
723gets larger than twice the use after the previous collection. 725gets larger than twice the total after the previous major collection.
724The default value is 100; the maximum value is 1000. 726The default value is 100.
727
728The major-minor multiplier controls the shift back to minor collections.
729For a multiplier @M{x},
730the collector will shift back to minor collections
731after a major collection collects at least @M{x%} of the allocated objects.
732In particular, for a multiplier of 0,
733the collector will immediately shift back to minor collections
734after doing one cycle of major collections.
735The default value is 20.
725 736
726} 737}
727 738
@@ -3311,9 +3322,8 @@ Returns the remainder of dividing the current amount of bytes of
3311memory in use by Lua by 1024. 3322memory in use by Lua by 1024.
3312} 3323}
3313 3324
3314@item{@id{LUA_GCSTEP} @T{(int stepsize)}| 3325@item{@id{LUA_GCSTEP}|
3315Performs an incremental step of garbage collection, 3326Performs a step of garbage collection.
3316corresponding to the allocation of @id{stepsize} Kbytes.
3317} 3327}
3318 3328
3319@item{@id{LUA_GCISRUNNING}| 3329@item{@id{LUA_GCISRUNNING}|
@@ -3321,13 +3331,13 @@ Returns a boolean that tells whether the collector is running
3321(i.e., not stopped). 3331(i.e., not stopped).
3322} 3332}
3323 3333
3324@item{@id{LUA_GCINC} (int pause, int stepmul, stepsize)| 3334@item{@id{LUA_GCINC} (int pause, int stepmul, int stepsize)|
3325Changes the collector to incremental mode 3335Changes the collector to incremental mode
3326with the given parameters @see{incmode}. 3336with the given parameters @see{incmode}.
3327Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). 3337Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
3328} 3338}
3329 3339
3330@item{@id{LUA_GCGEN} (int minormul, int majormul)| 3340@item{@id{LUA_GCGEN} (int minormul, int minormajor, int majorminor)|
3331Changes the collector to generational mode 3341Changes the collector to generational mode
3332with the given parameters @see{genmode}. 3342with the given parameters @see{genmode}.
3333Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}). 3343Returns the previous mode (@id{LUA_GCGEN} or @id{LUA_GCINC}).
@@ -6312,13 +6322,14 @@ gives the exact number of bytes in use by Lua.
6312 6322
6313@item{@St{step}| 6323@item{@St{step}|
6314Performs a garbage-collection step. 6324Performs a garbage-collection step.
6315The step @Q{size} is controlled by @id{arg}. 6325In incremental mode,
6316With a zero value, 6326that step corresponds to the current step size;
6317the collector will perform one basic (indivisible) step. 6327the function returns @true if the step finished a collection cycle.
6318For non-zero values, 6328In generational mode,
6319the collector will perform as if that amount of memory 6329the step performs a full minor collection or
6320(in Kbytes) had been allocated by Lua. 6330a major collection,
6321Returns @true if the step finished a collection cycle. 6331if the collector has scheduled one;
6332the function returns @true if the step performed a major collection.
6322} 6333}
6323 6334
6324@item{@St{isrunning}| 6335@item{@St{isrunning}|
@@ -6332,15 +6343,15 @@ This option can be followed by three numbers:
6332the garbage-collector pause, 6343the garbage-collector pause,
6333the step multiplier, 6344the step multiplier,
6334and the step size @see{incmode}. 6345and the step size @see{incmode}.
6335A zero means to not change that value. 6346A -1 or absent value means to not change that value.
6336} 6347}
6337 6348
6338@item{@St{generational}| 6349@item{@St{generational}|
6339Change the collector mode to generational. 6350Change the collector mode to generational.
6340This option can be followed by two numbers: 6351This option can be followed by three numbers:
6341the garbage-collector minor multiplier 6352the garbage-collector minor multiplier,
6342and the major multiplier @see{genmode}. 6353the minor-major multiplier, and the major-minor multiplier @see{genmode}.
6343A zero means to not change that value. 6354A -1 or absent value means to not change that value.
6344} 6355}
6345 6356
6346} 6357}
@@ -9229,6 +9240,9 @@ declare a local variable with the same name in the loop body.
9229@itemize{ 9240@itemize{
9230 9241
9231@item{ 9242@item{
9243There were several changes in the parameters
9244for the options @St{incremental} and @St{generational}
9245of the function @Lid{collectgarbage}.
9232} 9246}
9233 9247
9234} 9248}
@@ -9245,6 +9259,12 @@ it is equivalent to @Lid{lua_closethread} with
9245@id{from} being @id{NULL}. 9259@id{from} being @id{NULL}.
9246} 9260}
9247 9261
9262@item{
9263There were several changes in the parameters
9264for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN}
9265of the function @Lid{lua_gc}.
9266}
9267
9248} 9268}
9249 9269
9250} 9270}