aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-02-13 12:46:38 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-02-13 12:46:38 -0200
commitde3b1c9b53d74de4f22fe75b801cc57e1ba2840e (patch)
tree68b9034ce23a2a359a5f6f674dbad05e4b796e6a
parent733c58595bb57541e38275103fade1330aeb839d (diff)
downloadlua-de3b1c9b53d74de4f22fe75b801cc57e1ba2840e.tar.gz
lua-de3b1c9b53d74de4f22fe75b801cc57e1ba2840e.tar.bz2
lua-de3b1c9b53d74de4f22fe75b801cc57e1ba2840e.zip
better control for number of finalizers called at each GC cycle
(increases progressively)
-rw-r--r--lgc.c62
-rw-r--r--lgc.h5
-rw-r--r--lstate.c13
-rw-r--r--lstate.h3
4 files changed, 52 insertions, 31 deletions
diff --git a/lgc.c b/lgc.c
index 61162d42..515267e7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.170 2014/02/11 12:28:47 roberto Exp roberto $ 2** $Id: lgc.c,v 2.171 2014/02/13 12:11:34 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -33,8 +33,8 @@
33/* maximum number of elements to sweep in each single step */ 33/* maximum number of elements to sweep in each single step */
34#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) 34#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
35 35
36/* maximum number of finalizers to call in each GC step */ 36/* cost of calling one finalizer */
37#define GCFINALIZENUM 4 37#define GCFINALIZECOST GCSWEEPCOST
38 38
39 39
40/* 40/*
@@ -960,6 +960,7 @@ static l_mem atomic (lua_State *L) {
960 origweak = g->weak; origall = g->allweak; 960 origweak = g->weak; origall = g->allweak;
961 work += g->GCmemtrav; /* stop counting (objects being finalized) */ 961 work += g->GCmemtrav; /* stop counting (objects being finalized) */
962 separatetobefnz(g, 0); /* separate objects to be finalized */ 962 separatetobefnz(g, 0); /* separate objects to be finalized */
963 g->gcfinnum = 1; /* there may be objects to be finalized */
963 markbeingfnz(g); /* mark objects that will be finalized */ 964 markbeingfnz(g); /* mark objects that will be finalized */
964 propagateall(g); /* remark, to propagate 'resurrection' */ 965 propagateall(g); /* remark, to propagate 'resurrection' */
965 work -= g->GCmemtrav; /* restart counting */ 966 work -= g->GCmemtrav; /* restart counting */
@@ -1014,7 +1015,7 @@ static lu_mem singlestep (lua_State *L) {
1014 int sw; 1015 int sw;
1015 propagateall(g); /* make sure gray list is empty */ 1016 propagateall(g); /* make sure gray list is empty */
1016 g->GCestimate = g->GCmemtrav; /* save what was counted */; 1017 g->GCestimate = g->GCmemtrav; /* save what was counted */;
1017 work = atomic(L); /* add what was traversed by 'atomic' */ 1018 work = atomic(L); /* work is what was traversed by 'atomic' */
1018 g->GCestimate += work; /* estimate of total memory traversed */ 1019 g->GCestimate += work; /* estimate of total memory traversed */
1019 sw = entersweep(L); 1020 sw = entersweep(L);
1020 return work + sw * GCSWEEPCOST; 1021 return work + sw * GCSWEEPCOST;
@@ -1034,8 +1035,13 @@ static lu_mem singlestep (lua_State *L) {
1034 case GCSswpend: { /* finish sweeps */ 1035 case GCSswpend: { /* finish sweeps */
1035 makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ 1036 makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */
1036 checkSizes(L, g); 1037 checkSizes(L, g);
1038 g->gcstate = GCScallfin;
1039 return 0;
1040 }
1041 case GCScallfin: { /* state to finish calling finalizers */
1042 /* do nothing here; should be handled by 'luaC_forcestep' */
1037 g->gcstate = GCSpause; /* finish collection */ 1043 g->gcstate = GCSpause; /* finish collection */
1038 return GCSWEEPCOST; 1044 return 0;
1039 } 1045 }
1040 default: lua_assert(0); return 0; 1046 default: lua_assert(0); return 0;
1041 } 1047 }
@@ -1053,7 +1059,25 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1053} 1059}
1054 1060
1055 1061
1056static void incstep (lua_State *L) { 1062/*
1063** run a few finalizers
1064*/
1065static int dosomefinalization (lua_State *L) {
1066 global_State *g = G(L);
1067 unsigned int i;
1068 lua_assert(!g->tobefnz || g->gcfinnum > 0);
1069 for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
1070 GCTM(L, 1); /* call one finalizer */
1071 g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */
1072 : g->gcfinnum * 2; /* else call a few more next time */
1073 return i;
1074}
1075
1076
1077/*
1078** performs a basic GC step
1079*/
1080void luaC_forcestep (lua_State *L) {
1057 global_State *g = G(L); 1081 global_State *g = G(L);
1058 l_mem debt = g->GCdebt; 1082 l_mem debt = g->GCdebt;
1059 int stepmul = g->gcstepmul; 1083 int stepmul = g->gcstepmul;
@@ -1061,33 +1085,27 @@ static void incstep (lua_State *L) {
1061 /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ 1085 /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */
1062 debt = (debt / STEPMULADJ) + 1; 1086 debt = (debt / STEPMULADJ) + 1;
1063 debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; 1087 debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
1064 do { /* always perform at least one single step */ 1088 do {
1065 lu_mem work = singlestep(L); /* do some work */ 1089 if (g->gcstate == GCScallfin && g->tobefnz) {
1066 debt -= work; 1090 unsigned int n = dosomefinalization(L);
1091 debt -= (n * GCFINALIZECOST);
1092 }
1093 else { /* perform one single step */
1094 lu_mem work = singlestep(L);
1095 debt -= work;
1096 }
1067 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); 1097 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
1068 if (g->gcstate == GCSpause) 1098 if (g->gcstate == GCSpause)
1069 setpause(g, g->GCestimate); /* pause until next cycle */ 1099 setpause(g, g->GCestimate); /* pause until next cycle */
1070 else { 1100 else {
1071 debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ 1101 debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */
1072 luaE_setdebt(g, debt); 1102 luaE_setdebt(g, debt);
1103 dosomefinalization(L);
1073 } 1104 }
1074} 1105}
1075 1106
1076 1107
1077/* 1108/*
1078** performs a basic GC step
1079*/
1080void luaC_forcestep (lua_State *L) {
1081 global_State *g = G(L);
1082 int i;
1083 incstep(L);
1084 /* run a few finalizers (or all of them at the end of a collect cycle) */
1085 for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
1086 GCTM(L, 1); /* call one finalizer */
1087}
1088
1089
1090/*
1091** performs a basic GC step when collector is running 1109** performs a basic GC step when collector is running
1092*/ 1110*/
1093void luaC_step (lua_State *L) { 1111void luaC_step (lua_State *L) {
diff --git a/lgc.h b/lgc.h
index c4e1f3b0..a9e497c7 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.77 2014/02/11 12:18:12 roberto Exp roberto $ 2** $Id: lgc.h,v 2.78 2014/02/13 12:11:34 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -43,7 +43,8 @@
43#define GCSswpfinobj 4 43#define GCSswpfinobj 4
44#define GCSswptobefnz 5 44#define GCSswptobefnz 5
45#define GCSswpend 6 45#define GCSswpend 6
46#define GCSpause 7 46#define GCScallfin 7
47#define GCSpause 8
47 48
48 49
49#define issweepphase(g) \ 50#define issweepphase(g) \
diff --git a/lstate.c b/lstate.c
index 3a33390d..4c768c07 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.117 2014/02/11 12:18:12 roberto Exp roberto $ 2** $Id: lstate.c,v 2.118 2014/02/13 12:11:34 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -214,10 +214,10 @@ static void f_luaopen (lua_State *L, void *ud) {
214 214
215 215
216/* 216/*
217** preinitialize a state with consistent values without allocating 217** preinitialize a thread with consistent values without allocating
218** any memory (to avoid errors) 218** any memory (to avoid errors)
219*/ 219*/
220static void preinit_state (lua_State *L, global_State *g) { 220static void preinit_thread (lua_State *L, global_State *g) {
221 G(L) = g; 221 G(L) = g;
222 L->stack = NULL; 222 L->stack = NULL;
223 L->ci = NULL; 223 L->ci = NULL;
@@ -264,7 +264,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
264 g->mainthread->next = obj2gco(L1); 264 g->mainthread->next = obj2gco(L1);
265 setthvalue(L, L->top, L1); 265 setthvalue(L, L->top, L1);
266 api_incr_top(L); 266 api_incr_top(L);
267 preinit_state(L1, g); 267 preinit_thread(L1, g);
268 L1->hookmask = L->hookmask; 268 L1->hookmask = L->hookmask;
269 L1->basehookcount = L->basehookcount; 269 L1->basehookcount = L->basehookcount;
270 L1->hook = L->hook; 270 L1->hook = L->hook;
@@ -298,8 +298,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
298 L->tt = LUA_TTHREAD; 298 L->tt = LUA_TTHREAD;
299 g->currentwhite = bitmask(WHITE0BIT); 299 g->currentwhite = bitmask(WHITE0BIT);
300 L->marked = luaC_white(g); 300 L->marked = luaC_white(g);
301 g->gckind = KGC_NORMAL; 301 preinit_thread(L, g);
302 preinit_state(L, g);
303 g->frealloc = f; 302 g->frealloc = f;
304 g->ud = ud; 303 g->ud = ud;
305 g->mainthread = L; 304 g->mainthread = L;
@@ -313,12 +312,14 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
313 g->panic = NULL; 312 g->panic = NULL;
314 g->version = NULL; 313 g->version = NULL;
315 g->gcstate = GCSpause; 314 g->gcstate = GCSpause;
315 g->gckind = KGC_NORMAL;
316 g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; 316 g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
317 g->sweepgc = NULL; 317 g->sweepgc = NULL;
318 g->gray = g->grayagain = NULL; 318 g->gray = g->grayagain = NULL;
319 g->weak = g->ephemeron = g->allweak = NULL; 319 g->weak = g->ephemeron = g->allweak = NULL;
320 g->totalbytes = sizeof(LG); 320 g->totalbytes = sizeof(LG);
321 g->GCdebt = 0; 321 g->GCdebt = 0;
322 g->gcfinnum = 0;
322 g->gcpause = LUAI_GCPAUSE; 323 g->gcpause = LUAI_GCPAUSE;
323 g->gcstepmul = LUAI_GCMUL; 324 g->gcstepmul = LUAI_GCMUL;
324 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 325 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
diff --git a/lstate.h b/lstate.h
index 13b2108c..4acdee84 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.98 2014/02/11 12:18:12 roberto Exp roberto $ 2** $Id: lstate.h,v 2.99 2014/02/13 12:11:34 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -125,6 +125,7 @@ typedef struct global_State {
125 GCObject *tobefnz; /* list of userdata to be GC */ 125 GCObject *tobefnz; /* list of userdata to be GC */
126 GCObject *fixedgc; /* list of objects not to be collected */ 126 GCObject *fixedgc; /* list of objects not to be collected */
127 Mbuffer buff; /* temporary buffer for string concatenation */ 127 Mbuffer buff; /* temporary buffer for string concatenation */
128 unsigned int gcfinnum; /* number of finalizers to call in each GC step */
128 int gcpause; /* size of pause between successive GCs */ 129 int gcpause; /* size of pause between successive GCs */
129 int gcstepmul; /* GC `granularity' */ 130 int gcstepmul; /* GC `granularity' */
130 lua_CFunction panic; /* to be called in unprotected errors */ 131 lua_CFunction panic; /* to be called in unprotected errors */