浏览代码

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)
 #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.
 ** Convert an acceptable index to a pointer to its respective value.
 ** Non-valid indices return the special nil value 'G(L)->nilvalue'.
 ** 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);
   ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
   setsvalue2s(L, L->top.p, ts);
   setsvalue2s(L, L->top.p, ts);
   api_incr_top(L);
   api_incr_top(L);
+  advancegc(L, len);
   luaC_checkGC(L);
   luaC_checkGC(L);
   lua_unlock(L);
   lua_unlock(L);
   return getstr(ts);
   return getstr(ts);
@@ -544,6 +555,8 @@ LUA_API const char *lua_pushextlstring (lua_State *L,
   ts = luaS_newextlstr (L, s, len, falloc, ud);
   ts = luaS_newextlstr (L, s, len, falloc, ud);
   setsvalue2s(L, L->top.p, ts);
   setsvalue2s(L, L->top.p, ts);
   api_incr_top(L);
   api_incr_top(L);
+  if (falloc != NULL)  /* non-static string? */
+    advancegc(L, len);  /* count its memory */
   luaC_checkGC(L);
   luaC_checkGC(L);
   lua_unlock(L);
   lua_unlock(L);
   return getstr(ts);
   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);
   u = luaS_newudata(L, size, nuvalue);
   setuvalue(L, s2v(L->top.p), u);
   setuvalue(L, s2v(L->top.p), u);
   api_incr_top(L);
   api_incr_top(L);
+  advancegc(L, size);
   luaC_checkGC(L);
   luaC_checkGC(L);
   lua_unlock(L);
   lua_unlock(L);
   return getudatamem(u);
   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 threshold = applygcparam(g, PAUSE, g->marked);
   l_obj debt = threshold - gettotalobjs(g);
   l_obj debt = threshold - gettotalobjs(g);
   if (debt < 0) debt = 0;
   if (debt < 0) debt = 0;
+//printf("pause: %ld  %ld\n", debt, g->marked);
   luaE_setdebt(g, debt);
   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:
 ** Decide whether to shift to major mode. It tests two conditions:
 ** 1) Whether the number of added old objects in this collection is more
 ** 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
 ** created between minor collections. Except for forward barriers, it
 ** is the maximum number of objects that can become old in each minor
 ** is the maximum number of objects that can become old in each minor
 ** collection.)
 ** 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
 ** than 'minormajor'% of the number of lived objects after the last
 ** major collection. (That percentage is computed in 'limit'.)
 ** 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 step = applygcparam(g, MINORMUL, g->GCmajorminor);
   l_obj limit = applygcparam(g, MINORMAJOR, 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;
   g->marked = marked + addedold1;
 
 
   /* decide whether to shift to major mode */
   /* 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 */
     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').
 ** since the last collection ('addedobjs').
 */
 */
 static int checkmajorminor (lua_State *L, global_State *g) {
 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 numobjs = gettotalobjs(g);
     l_obj addedobjs = numobjs - g->GCmajorminor;
     l_obj addedobjs = numobjs - g->GCmajorminor;
     l_obj limit = applygcparam(g, MAJORMINOR, addedobjs);
     l_obj limit = applygcparam(g, MAJORMINOR, addedobjs);
     l_obj tobecollected = numobjs - g->marked;
     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) {
     if (tobecollected > limit) {
       atomic2gen(L, g);  /* return to generational mode */
       atomic2gen(L, g);  /* return to generational mode */
       setminordebt(g);
       setminordebt(g);

+ 1 - 1
lgc.h

@@ -183,7 +183,7 @@
 /* incremental */
 /* incremental */
 
 
 /* Number of objects must be LUAI_GCPAUSE% before starting new cycle */
 /* 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
 /* Step multiplier. (Roughly, the collector handles LUAI_GCMUL% objects
    for each new allocated object.) */
    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.
 start a new cycle.
 A value of 200 means that the collector waits for
 A value of 200 means that the collector waits for
 the total number of objects to double before starting a new cycle.
 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
 The garbage-collector step size controls the
 size of each incremental step,
 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.
 Larger values make the collector more aggressive.
 Beware that values too small can
 Beware that values too small can
 make the collector too slow to ever finish a cycle.
 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,
 As a special case, a zero value means unlimited work,
 effectively producing a non-incremental, stop-the-world collector.
 effectively producing a non-incremental, stop-the-world collector.