GC local pause configurable

This commit is contained in:
Roberto Ierusalimschy 2013-09-13 13:21:52 -03:00
parent 06156e7575
commit 686e57cf9c
6 changed files with 41 additions and 35 deletions

7
lapi.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 2.188 2013/08/27 18:53:35 roberto Exp roberto $
** $Id: lapi.c,v 2.189 2013/09/11 20:15:31 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
@ -1086,6 +1086,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
g->gcpause = data;
break;
}
case LUA_GCSETLOCALPAUSE: {
res = g->gclocalpause;
g->gclocalpause = data;
break;
}
case LUA_GCSETSTEPMUL: {
res = g->gcstepmul;
g->gcstepmul = data;

View File

@ -1,5 +1,5 @@
/*
** $Id: lbaselib.c,v 1.280 2013/07/10 17:15:12 roberto Exp roberto $
** $Id: lbaselib.c,v 1.281 2013/08/05 16:58:28 roberto Exp roberto $
** Basic library
** See Copyright Notice in lua.h
*/
@ -174,9 +174,11 @@ static int luaB_rawset (lua_State *L) {
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul", "isrunning", NULL};
"count", "step", "setpause", "setstepmul",
"setlocalpause", "isrunning", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING};
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
LUA_GCSETLOCALPAUSE, LUA_GCISRUNNING};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
int ex = luaL_optint(L, 2, 0);
int res = lua_gc(L, o, ex);

46
lgc.c
View File

@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.163 2013/09/11 14:47:08 roberto Exp roberto $
** $Id: lgc.c,v 2.164 2013/09/11 14:56:15 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@ -24,12 +24,6 @@
/*
** How much memory to allocate before a new local collection
*/
#define GCLOCALPAUSE 8000
/*
** cost of sweeping one element (the size of a small object divided
** by some adjust for the sweep speed)
@ -149,7 +143,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(g->gcstate != GCSpause);
lua_assert(gch(o)->tt != LUA_TTABLE);
lua_assert(gch(o)->tt != LUA_TTABLE); /* tables use a back barrier */
if (keepinvariant(g)) /* must keep invariant? */
reallymarkobject(g, v); /* restore invariant */
else { /* sweep phase */
@ -888,19 +882,18 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
return; /* nothing to be done */
else { /* move 'o' to 'finobj' list */
GCObject **p;
GCheader *ho = gch(o);
if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */
if (g->sweepgc == &o->gch.next) { /* avoid removing current sweep object */
lua_assert(issweepphase(g));
g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
}
/* search for pointer pointing to 'o' */
p = (testbit(ho->marked, LOCALMARK)) ? &g->allgc : &g->localgc;
p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc;
for (; *p != o; p = &gch(*p)->next) { /* empty */ }
*p = ho->next; /* remove 'o' from its list */
p = (testbit(ho->marked, LOCALMARK)) ? &g->finobj : &g->localfin;
ho->next = *p; /* link it in a "fin" list */
*p = o->gch.next; /* remove 'o' from its list */
p = (testbit(o->gch.marked, LOCALMARK)) ? &g->finobj : &g->localfin;
o->gch.next = *p; /* link it in a "fin" list */
*p = o;
l_setbit(ho->marked, FINALIZEDBIT); /* mark it as such */
l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */
if (issweepphase(g))
makewhite(g, o); /* "sweep" object */
}
@ -1032,7 +1025,7 @@ static void setpause (global_State *g, l_mem estimate) {
? estimate * g->gcpause /* no overflow */
: MAX_LMEM; /* overflow; truncate to maximum */
g->GCthreshold = threshold;
luaE_setdebt(g, -GCLOCALPAUSE);
luaE_setdebt(g, -g->gclocalpause);
}
@ -1050,8 +1043,6 @@ static int entersweep (lua_State *L) {
g->gcstate = GCSswplocalgc;
lua_assert(g->sweepgc == NULL);
g->sweepgc = sweeptolive(L, &g->localgc, &n);
if (g->sweepgc == NULL) /* no live objects in local list? */
g->sweepgc = &g->localgc; /* 'sweepgc' cannot be NULL here */
return n;
}
@ -1099,7 +1090,7 @@ static l_mem atomic (lua_State *L) {
work += g->GCmemtrav; /* stop counting (objects being finalized) */
separatetobefnz(g, 0); /* separate objects to be finalized */
markbeingfnz(g); /* mark objects that will be finalized */
propagateall(g); /* remark, to propagate `preserveness' */
propagateall(g); /* remark, to propagate 'resurrection' */
work -= g->GCmemtrav; /* restart counting */
convergeephemerons(g);
/* at this point, all resurrected objects are marked. */
@ -1117,14 +1108,15 @@ static l_mem atomic (lua_State *L) {
static lu_mem sweepstep (lua_State *L, global_State *g,
int nextstate, GCObject **nextlist) {
g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
if (g->sweepgc) /* is there still something to sweep? */
return (GCSWEEPMAX * GCSWEEPCOST);
else { /* enter next state */
g->gcstate = nextstate;
g->sweepgc = nextlist;
return 0;
if (g->sweepgc) {
g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
if (g->sweepgc) /* is there still something to sweep? */
return (GCSWEEPMAX * GCSWEEPCOST);
}
/* else enter next state */
g->gcstate = nextstate;
g->sweepgc = nextlist;
return 0;
}
@ -1245,7 +1237,7 @@ void luaC_step (lua_State *L) {
luaC_forcestep(L); /* restart collection */
}
else
luaE_setdebt(g, -GCLOCALPAUSE);
luaE_setdebt(g, -g->gclocalpause);
}
}
else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */

View File

@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 2.112 2013/09/11 12:26:14 roberto Exp roberto $
** $Id: lstate.c,v 2.113 2013/09/11 14:09:55 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -30,6 +30,10 @@
#define LUAI_GCPAUSE 200 /* 200% */
#endif
#if !defined(LUAI_GCLOCALPAUSE)
#define LUAI_GCLOCALPAUSE (1000 * sizeof(TString))
#endif
#if !defined(LUAI_GCMUL)
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
#endif
@ -301,6 +305,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->totalbytes = sizeof(LG);
g->GCdebt = 0;
g->gcpause = LUAI_GCPAUSE;
g->gclocalpause = LUAI_GCLOCALPAUSE;
g->gcstepmul = LUAI_GCMUL;
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {

View File

@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 2.94 2013/09/05 19:31:49 roberto Exp roberto $
** $Id: lstate.h,v 2.95 2013/09/11 14:09:55 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -131,6 +131,7 @@ typedef struct global_State {
GCObject *fixedgc; /* list of objects not to be collected */
Mbuffer buff; /* temporary buffer for string concatenation */
int gcpause; /* size of pause between successive GCs */
int gclocalpause; /* size of pause between local collections */
int gcstepmul; /* GC `granularity' */
lua_CFunction panic; /* to be called in unprotected errors */
struct lua_State *mainthread;

5
lua.h
View File

@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.292 2013/07/05 14:29:51 roberto Exp roberto $
** $Id: lua.h,v 1.293 2013/08/05 16:58:28 roberto Exp roberto $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@ -288,7 +288,8 @@ LUA_API int (lua_status) (lua_State *L);
#define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
#define LUA_GCISRUNNING 8
#define LUA_GCSETLOCALPAUSE 8
#define LUA_GCISRUNNING 9
LUA_API int (lua_gc) (lua_State *L, int what, int data);