Przeglądaj źródła

GC local pause configurable

Roberto Ierusalimschy 12 lat temu
rodzic
commit
686e57cf9c
6 zmienionych plików z 41 dodań i 35 usunięć
  1. 6 1
      lapi.c
  2. 5 3
      lbaselib.c
  3. 19 27
      lgc.c
  4. 6 1
      lstate.c
  5. 2 1
      lstate.h
  6. 3 2
      lua.h

+ 6 - 1
lapi.c

@@ -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
 ** Lua API
 ** See Copyright Notice in lua.h
 ** 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;
       g->gcpause = data;
       break;
       break;
     }
     }
+    case LUA_GCSETLOCALPAUSE: {
+      res = g->gclocalpause;
+      g->gclocalpause = data;
+      break;
+    }
     case LUA_GCSETSTEPMUL: {
     case LUA_GCSETSTEPMUL: {
       res = g->gcstepmul;
       res = g->gcstepmul;
       g->gcstepmul = data;
       g->gcstepmul = data;

+ 5 - 3
lbaselib.c

@@ -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
 ** Basic library
 ** See Copyright Notice in lua.h
 ** 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 int luaB_collectgarbage (lua_State *L) {
   static const char *const opts[] = {"stop", "restart", "collect",
   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,
   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 o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
   int ex = luaL_optint(L, 2, 0);
   int ex = luaL_optint(L, 2, 0);
   int res = lua_gc(L, o, ex);
   int res = lua_gc(L, o, ex);

+ 19 - 27
lgc.c

@@ -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
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** 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
 ** cost of sweeping one element (the size of a small object divided
 ** by some adjust for the sweep speed)
 ** 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);
   global_State *g = G(L);
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
   lua_assert(g->gcstate != GCSpause);
   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? */
   if (keepinvariant(g))  /* must keep invariant? */
     reallymarkobject(g, v);  /* restore invariant */
     reallymarkobject(g, v);  /* restore invariant */
   else {  /* sweep phase */
   else {  /* sweep phase */
@@ -888,19 +882,18 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
     return;  /* nothing to be done */
     return;  /* nothing to be done */
   else {  /* move 'o' to 'finobj' list */
   else {  /* move 'o' to 'finobj' list */
     GCObject **p;
     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));
       lua_assert(issweepphase(g));
       g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
       g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
     }
     }
     /* search for pointer pointing to 'o' */
     /* 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 */ }
     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;
     *p = o;
-    l_setbit(ho->marked, FINALIZEDBIT);  /* mark it as such */
+    l_setbit(o->gch.marked, FINALIZEDBIT);  /* mark it as such */
     if (issweepphase(g))
     if (issweepphase(g))
       makewhite(g, o);  /* "sweep" object */
       makewhite(g, o);  /* "sweep" object */
   }
   }
@@ -1032,7 +1025,7 @@ static void setpause (global_State *g, l_mem estimate) {
             ? estimate * g->gcpause  /* no overflow */
             ? estimate * g->gcpause  /* no overflow */
             : MAX_LMEM;  /* overflow; truncate to maximum */
             : MAX_LMEM;  /* overflow; truncate to maximum */
   g->GCthreshold = threshold;
   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;
   g->gcstate = GCSswplocalgc;
   lua_assert(g->sweepgc == NULL);
   lua_assert(g->sweepgc == NULL);
   g->sweepgc = sweeptolive(L, &g->localgc, &n);
   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;
   return n;
 }
 }
 
 
@@ -1099,7 +1090,7 @@ static l_mem atomic (lua_State *L) {
   work += g->GCmemtrav;  /* stop counting (objects being finalized) */
   work += g->GCmemtrav;  /* stop counting (objects being finalized) */
   separatetobefnz(g, 0);  /* separate objects to be finalized */
   separatetobefnz(g, 0);  /* separate objects to be finalized */
   markbeingfnz(g);  /* mark objects that will 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 */
   work -= g->GCmemtrav;  /* restart counting */
   convergeephemerons(g);
   convergeephemerons(g);
   /* at this point, all resurrected objects are marked. */
   /* 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,
 static lu_mem sweepstep (lua_State *L, global_State *g,
                          int nextstate, GCObject **nextlist) {
                          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 */
         luaC_forcestep(L);  /* restart collection */
       }
       }
       else
       else
-        luaE_setdebt(g, -GCLOCALPAUSE);
+        luaE_setdebt(g, -g->gclocalpause);
     }
     }
   }
   }
   else luaE_setdebt(g, -GCSTEPSIZE);  /* avoid being called too often */
   else luaE_setdebt(g, -GCSTEPSIZE);  /* avoid being called too often */

+ 6 - 1
lstate.c

@@ -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
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -30,6 +30,10 @@
 #define LUAI_GCPAUSE	200  /* 200% */
 #define LUAI_GCPAUSE	200  /* 200% */
 #endif
 #endif
 
 
+#if !defined(LUAI_GCLOCALPAUSE)
+#define LUAI_GCLOCALPAUSE	(1000 * sizeof(TString))
+#endif
+
 #if !defined(LUAI_GCMUL)
 #if !defined(LUAI_GCMUL)
 #define LUAI_GCMUL	200 /* GC runs 'twice the speed' of memory allocation */
 #define LUAI_GCMUL	200 /* GC runs 'twice the speed' of memory allocation */
 #endif
 #endif
@@ -301,6 +305,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->totalbytes = sizeof(LG);
   g->totalbytes = sizeof(LG);
   g->GCdebt = 0;
   g->GCdebt = 0;
   g->gcpause = LUAI_GCPAUSE;
   g->gcpause = LUAI_GCPAUSE;
+  g->gclocalpause = LUAI_GCLOCALPAUSE;
   g->gcstepmul = LUAI_GCMUL;
   g->gcstepmul = LUAI_GCMUL;
   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {

+ 2 - 1
lstate.h

@@ -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
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -131,6 +131,7 @@ typedef struct global_State {
   GCObject *fixedgc;  /* list of objects not to be collected */
   GCObject *fixedgc;  /* list of objects not to be collected */
   Mbuffer buff;  /* temporary buffer for string concatenation */
   Mbuffer buff;  /* temporary buffer for string concatenation */
   int gcpause;  /* size of pause between successive GCs */
   int gcpause;  /* size of pause between successive GCs */
+  int gclocalpause;  /* size of pause between local collections */
   int gcstepmul;  /* GC `granularity' */
   int gcstepmul;  /* GC `granularity' */
   lua_CFunction panic;  /* to be called in unprotected errors */
   lua_CFunction panic;  /* to be called in unprotected errors */
   struct lua_State *mainthread;
   struct lua_State *mainthread;

+ 3 - 2
lua.h

@@ -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 - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
 ** 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_GCSTEP		5
 #define LUA_GCSETPAUSE		6
 #define LUA_GCSETPAUSE		6
 #define LUA_GCSETSTEPMUL	7
 #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);
 LUA_API int (lua_gc) (lua_State *L, int what, int data);