浏览代码

A few more tweaks in the garbage collector

Roberto Ierusalimschy 1 年之前
父节点
当前提交
7827c40c49
共有 5 个文件被更改,包括 33 次插入14 次删除
  1. 4 0
      config.lua
  2. 14 0
      lapi.c
  3. 12 11
      lgc.c
  4. 1 1
      lgc.h
  5. 2 2
      manual/manual.of

+ 4 - 0
config.lua

@@ -0,0 +1,4 @@
+collectgarbage("setparam", "minormul", 25)
+-- collectgarbage("generational")
+
+

+ 14 - 0
lapi.c

@@ -53,6 +53,16 @@ const char lua_ident[] =
 #define isupvalue(i)		((i) < LUA_REGISTRYINDEX)
 
 
+/* Advance the garbage collector when creating large objects */
+static void advancegc (lua_State *L, size_t delta) {
+  delta >>= 5;  /* one object for each 32 bytes (empirical) */
+  if (delta > 0) {
+    global_State *g = G(L);
+    luaE_setdebt(g, g->GCdebt - delta);
+  }
+}
+
+
 /*
 ** Convert an acceptable index to a pointer to its respective value.
 ** Non-valid indices return the special nil value 'G(L)->nilvalue'.
@@ -530,6 +540,7 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
   ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
   setsvalue2s(L, L->top.p, ts);
   api_incr_top(L);
+  advancegc(L, len);
   luaC_checkGC(L);
   lua_unlock(L);
   return getstr(ts);
@@ -544,6 +555,8 @@ LUA_API const char *lua_pushextlstring (lua_State *L,
   ts = luaS_newextlstr (L, s, len, falloc, ud);
   setsvalue2s(L, L->top.p, ts);
   api_incr_top(L);
+  if (falloc != NULL)  /* non-static string? */
+    advancegc(L, len);  /* count its memory */
   luaC_checkGC(L);
   lua_unlock(L);
   return getstr(ts);
@@ -1336,6 +1349,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) {
   u = luaS_newudata(L, size, nuvalue);
   setuvalue(L, s2v(L->top.p), u);
   api_incr_top(L);
+  advancegc(L, size);
   luaC_checkGC(L);
   lua_unlock(L);
   return getudatamem(u);

+ 12 - 11
lgc.c

@@ -1052,6 +1052,7 @@ static void setpause (global_State *g) {
   l_obj threshold = applygcparam(g, PAUSE, g->marked);
   l_obj debt = threshold - gettotalobjs(g);
   if (debt < 0) debt = 0;
+//printf("pause: %ld  %ld\n", debt, g->marked);
   luaE_setdebt(g, debt);
 }
 
@@ -1246,7 +1247,7 @@ static void minor2inc (lua_State *L, global_State *g, int kind) {
 /*
 ** Decide whether to shift to major mode. It tests two conditions:
 ** 1) Whether the number of added old objects in this collection is more
-** than half the number of new objects. ("step" is the number of objects
+** than half the number of new objects. ('step' is the number of objects
 ** created between minor collections. Except for forward barriers, it
 ** is the maximum number of objects that can become old in each minor
 ** collection.)
@@ -1254,15 +1255,11 @@ static void minor2inc (lua_State *L, global_State *g, int kind) {
 ** than 'minormajor'% of the number of lived objects after the last
 ** major collection. (That percentage is computed in 'limit'.)
 */
-static int checkminormajor (lua_State *L, global_State *g, l_obj addedold1) {
+static int checkminormajor (global_State *g, l_obj addedold1) {
   l_obj step = applygcparam(g, MINORMUL, g->GCmajorminor);
   l_obj limit = applygcparam(g, MINORMAJOR, g->GCmajorminor);
-//printf("-> major? %ld %ld %ld %ld (%ld)\n", g->marked, limit, step, addedold1, gettotalobjs(g));
-  if (addedold1 >= (step >> 1) || g->marked >= limit) {
-    minor2inc(L, g, KGC_GENMAJOR);  /* go to major mode */
-    return 1;
-  }
-  return 0;  /* stay in minor mode */
+//printf("-> (%ld) major? marked: %ld  limit: %ld  step: %ld  addedold1: %ld)\n", gettotalobjs(g), g->marked, limit, step, addedold1);
+  return (addedold1 >= (step >> 1) || g->marked >= limit);
 }
 
 /*
@@ -1309,7 +1306,11 @@ static void youngcollection (lua_State *L, global_State *g) {
   g->marked = marked + addedold1;
 
   /* decide whether to shift to major mode */
-  if (!checkminormajor(L, g, addedold1))
+  if (checkminormajor(g, addedold1)) {
+    minor2inc(L, g, KGC_GENMAJOR);  /* go to major mode */
+    g->marked = 0;  /* avoid pause in first major cycle */
+  }
+  else
     finishgencycle(L, g);  /* still in minor mode; finish it */
 }
 
@@ -1401,12 +1402,12 @@ static void fullgen (lua_State *L, global_State *g) {
 ** since the last collection ('addedobjs').
 */
 static int checkmajorminor (lua_State *L, global_State *g) {
-  if (g->gckind == KGC_GENMAJOR) {
+  if (g->gckind == KGC_GENMAJOR) {  /* generational mode? */
     l_obj numobjs = gettotalobjs(g);
     l_obj addedobjs = numobjs - g->GCmajorminor;
     l_obj limit = applygcparam(g, MAJORMINOR, addedobjs);
     l_obj tobecollected = numobjs - g->marked;
-//printf("-> minor? %ld %ld %ld\n", tobecollected, limit, numobjs);
+//printf("(%ld) -> minor? tobecollected: %ld  limit: %ld\n", numobjs, tobecollected, limit);
     if (tobecollected > limit) {
       atomic2gen(L, g);  /* return to generational mode */
       setminordebt(g);

+ 1 - 1
lgc.h

@@ -183,7 +183,7 @@
 /* incremental */
 
 /* Number of objects must be LUAI_GCPAUSE% before starting new cycle */
-#define LUAI_GCPAUSE    300
+#define LUAI_GCPAUSE    200
 
 /* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects
    for each new allocated object.) */

+ 2 - 2
manual/manual.of

@@ -664,7 +664,7 @@ Values equal to or less than 100 mean the collector will not wait to
 start a new cycle.
 A value of 200 means that the collector waits for
 the total number of objects to double before starting a new cycle.
-The default value is 300; the maximum value is 1000.
+The default value is 200.
 
 The garbage-collector step size controls the
 size of each incremental step,
@@ -681,7 +681,7 @@ in each step, @M{n%} objects for each created object.
 Larger values make the collector more aggressive.
 Beware that values too small can
 make the collector too slow to ever finish a cycle.
-The default value is 200; the maximum value is 1000.
+The default value is 200.
 As a special case, a zero value means unlimited work,
 effectively producing a non-incremental, stop-the-world collector.