diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-02-13 12:46:38 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-02-13 12:46:38 -0200 |
commit | de3b1c9b53d74de4f22fe75b801cc57e1ba2840e (patch) | |
tree | 68b9034ce23a2a359a5f6f674dbad05e4b796e6a | |
parent | 733c58595bb57541e38275103fade1330aeb839d (diff) | |
download | lua-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.c | 62 | ||||
-rw-r--r-- | lgc.h | 5 | ||||
-rw-r--r-- | lstate.c | 13 | ||||
-rw-r--r-- | lstate.h | 3 |
4 files changed, 52 insertions, 31 deletions
@@ -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 | ||
1056 | static void incstep (lua_State *L) { | 1062 | /* |
1063 | ** run a few finalizers | ||
1064 | */ | ||
1065 | static 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 | */ | ||
1080 | void 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 | */ | ||
1080 | void 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 | */ |
1093 | void luaC_step (lua_State *L) { | 1111 | void luaC_step (lua_State *L) { |
@@ -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) \ |
@@ -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 | */ |
220 | static void preinit_state (lua_State *L, global_State *g) { | 220 | static 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; |
@@ -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 */ |