Sfoglia il codice sorgente

Several tweaks in the garbage collector

- back with step size in collectgarbage("step")
- adjustments in defaults for some GC parameters
- adjustments in 'luaO_codeparam'
Roberto Ierusalimschy 1 anno fa
parent
commit
12b6f610b0
8 ha cambiato i file con 98 aggiunte e 56 eliminazioni
  1. 12 6
      lapi.c
  2. 4 6
      lbaselib.c
  3. 2 2
      lgc.h
  4. 9 9
      lobject.c
  5. 2 2
      lobject.h
  6. 39 30
      manual/manual.of
  7. 2 0
      testes/files.lua
  8. 28 1
      testes/gc.lua

+ 12 - 6
lapi.c

@@ -416,10 +416,11 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
     luaC_checkGC(L);
     o = index2value(L, idx);  /* previous call may reallocate the stack */
   }
-  if (len != NULL)
-    *len = tsslen(tsvalue(o));
   lua_unlock(L);
-  return getstr(tsvalue(o));
+  if (len != NULL)
+    return getlstr(tsvalue(o), *len);
+  else
+    return getstr(tsvalue(o));
 }
 
 
@@ -1174,11 +1175,16 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
     }
     case LUA_GCSTEP: {
       lu_byte oldstp = g->gcstp;
+      l_obj n = va_arg(argp, int);
+      int work = 0;  /* true if GC did some work */
       g->gcstp = 0;  /* allow GC to run (other bits must be zero here) */
-      luaC_step(L);  /* run one basic step */
-      g->gcstp = oldstp;  /* restore previous state */
-      if (g->gcstate == GCSpause)  /* end of cycle? */
+      if (n <= 0)
+        n = g->GCdebt;  /* force to run one basic step */
+      luaE_setdebt(g, g->GCdebt - n);
+      luaC_condGC(L, (void)0, work = 1);
+      if (work && g->gcstate == GCSpause)  /* end of cycle? */
         res = 1;  /* signal it */
+      g->gcstp = oldstp;  /* restore previous state */
       break;
     }
     case LUA_GCISRUNNING: {

+ 4 - 6
lbaselib.c

@@ -213,7 +213,8 @@ static int luaB_collectgarbage (lua_State *L) {
       return 1;
     }
     case LUA_GCSTEP: {
-      int res = lua_gc(L, o);
+      lua_Integer n = luaL_optinteger(L, 2, 0);
+      int res = lua_gc(L, o, (int)n);
       checkvalres(res);
       lua_pushboolean(L, res);
       return 1;
@@ -239,7 +240,7 @@ static int luaB_collectgarbage (lua_State *L) {
         LUA_GCPPAUSE, LUA_GCPSTEPMUL, LUA_GCPSTEPSIZE};
       int p = pnum[luaL_checkoption(L, 2, NULL, params)];
       lua_Integer value = luaL_checkinteger(L, 3);
-      lua_pushinteger(L, lua_gc(L, o, p, value));
+      lua_pushinteger(L, lua_gc(L, o, p, (int)value));
       return 1;
     }
     default: {
@@ -337,10 +338,7 @@ static int load_aux (lua_State *L, int status, int envidx) {
 
 static const char *getmode (lua_State *L, int idx) {
   const char *mode = luaL_optstring(L, idx, "bt");
-  int i = 0;
-  if (mode[i] == 'b') i++;
-  if (mode[i] == 't') i++;
-  if (mode[i] != '\0')
+  if (strchr(mode, 'B') != NULL)  /* Lua code cannot use fixed buffers */
     luaL_argerror(L, idx, "invalid mode");
   return mode;
 }

+ 2 - 2
lgc.h

@@ -171,13 +171,13 @@
 ** Major collections will shift to minor ones after a collection
 ** collects at least LUAI_MAJORMINOR% of the new objects.
 */
-#define LUAI_MAJORMINOR         80
+#define LUAI_MAJORMINOR         50
 
 /*
 ** A young (minor) collection will run after creating LUAI_GENMINORMUL%
 ** new objects.
 */
-#define LUAI_GENMINORMUL         20
+#define LUAI_GENMINORMUL         25
 
 
 /* incremental */

+ 9 - 9
lobject.c

@@ -50,22 +50,22 @@ int luaO_ceillog2 (unsigned int x) {
 }
 
 /*
-** Encodes 'p'% as a floating-point byte, represented as (eeeeexxx).
+** Encodes 'p'% as a floating-point byte, represented as (eeeexxxx).
 ** The exponent is represented using excess-7. Mimicking IEEE 754, the
 ** representation normalizes the number when possible, assuming an extra
-** 1 before the mantissa (xxx) and adding one to the exponent (eeeeexxx)
-** to signal that. So, the real value is (1xxx) * 2^(eeeee - 8) if
-** eeeee != 0, and (xxx) * 2^-7 otherwise.
+** 1 before the mantissa (xxxx) and adding one to the exponent (eeee)
+** to signal that. So, the real value is (1xxxx) * 2^(eeee - 7 - 1) if
+** eeee != 0, and (xxxx) * 2^-7 otherwise (subnormal numbers).
 */
 unsigned int luaO_codeparam (unsigned int p) {
-  if (p >= (cast(lu_mem, 0xF) << 0xF) / 128 * 100)  /* overflow? */
+  if (p >= (cast(lu_mem, 0x1F) << (0xF - 7 - 1)) * 100u)  /* overflow? */
     return 0xFF;  /* return maximum value */
   else {
-    p = (p * 128u) / 100;
-    if (p <= 0xF)
-      return p;
+    p = (cast(l_uint32, p) * 128 + 99) / 100;  /* round up the division */
+    if (p < 0x10)  /* subnormal number? */
+      return p;  /* exponent bits are already zero; nothing else to do */
     else {
-      int log = luaO_ceillog2(p + 1) - 5;
+      int log = luaO_ceillog2(p + 1) - 5;  /* preserve 5 bits */
       return ((p >> log) - 0x10) | ((log + 1) << 4);
     }
   }

+ 2 - 2
lobject.h

@@ -427,8 +427,8 @@ typedef struct TString {
 ** Get string and length */
 #define getlstr(ts, len)  \
 	(strisshr(ts) \
-	? (cast_void(len = (ts)->shrlen), rawgetshrstr(ts)) \
-	: (cast_void(len = (ts)->u.lnglen), (ts)->contents))
+	? (cast_void((len) = (ts)->shrlen), rawgetshrstr(ts)) \
+	: (cast_void((len) = (ts)->u.lnglen), (ts)->contents))
 
 /* }================================================================== */
 

+ 39 - 30
manual/manual.of

@@ -666,18 +666,6 @@ 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 garbage-collector step multiplier
-controls the speed of the collector relative to
-object creation,
-that is,
-how many objects it marks or sweeps for each object created.
-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.
-As a special case, a zero value means unlimited work,
-effectively producing a non-incremental, stop-the-world collector.
-
 The garbage-collector step size controls the
 size of each incremental step,
 specifically how many objects the interpreter creates
@@ -686,6 +674,17 @@ A value of @M{n} means the interpreter will create
 approximately @M{n} objects between steps.
 The default value is 250.
 
+The garbage-collector step multiplier
+controls the size of each GC step.
+A value of @M{n} means the interpreter will mark or sweep,
+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.
+As a special case, a zero value means unlimited work,
+effectively producing a non-incremental, stop-the-world collector.
+
 }
 
 @sect3{genmode| @title{Generational Garbage Collection}
@@ -707,11 +706,12 @@ and the @def{major-minor multiplier}.
 The minor multiplier controls the frequency of minor collections.
 For a minor multiplier @M{x},
 a new minor collection will be done when the number of objects
-grows @M{x%} larger than the number in use just after the last collection.
+grows @M{x%} larger than the number in use just
+after the last major collection.
 For instance, for a multiplier of 20,
 the collector will do a minor collection when the number of objects
 gets 20% larger than the total after the last major collection.
-The default value is 20.
+The default value is 25.
 
 The minor-major multiplier controls the shift to major collections.
 For a multiplier @M{x},
@@ -728,11 +728,10 @@ For a multiplier @M{x},
 the collector will shift back to minor collections
 after a major collection collects at least @M{x%}
 of the objects allocated during the last cycle.
-
 In particular, for a multiplier of 0,
 the collector will immediately shift back to minor collections
 after doing one cycle of major collections.
-The default value is 80.
+The default value is 50.
 
 }
 
@@ -3327,7 +3326,7 @@ Returns the remainder of dividing the current amount of bytes of
 memory in use by Lua by 1024.
 }
 
-@item{@defid{LUA_GCSTEP}|
+@item{@defid{LUA_GCSTEP} (int n)|
 Performs a step of garbage collection.
 }
 
@@ -3686,9 +3685,12 @@ Moreover, for a fixed buffer,
 the reader function should return the entire chunk in the first read.
 (As an example, @Lid{luaL_loadbufferx} does that.)
 
-@id{lua_load} uses the stack internally,
-so the reader function must always leave the stack
-unmodified when returning.
+The function @Lid{lua_load} fully preserves the Lua stack
+through the calls to the reader function,
+except that it may push some values for internal use
+before the first call,
+and it restores the stack size to its original size plus one
+(for the pushed result) after the last call.
 
 @id{lua_load} can return
 @Lid{LUA_OK}, @Lid{LUA_ERRSYNTAX}, or @Lid{LUA_ERRMEM}.
@@ -6344,13 +6346,24 @@ gives the exact number of bytes in use by Lua.
 
 @item{@St{step}|
 Performs a garbage-collection step.
+This option may be followed by an extra argument,
+an integer with the step size.
+The default for this argument is zero.
+
+If the size is a positive @id{n},
+the collector acts as if @id{n} new objects have been created.
+If the size is zero,
+the collector performs a basic step.
 In incremental mode,
-that step corresponds to the current step size;
-the function returns @true if the step finished a collection cycle.
+a basic step corresponds to the current step size.
 In generational mode,
-the step performs a full minor collection or
+a basic step performs a full minor collection or
 a major collection,
-if the collector has scheduled one;
+if the collector has scheduled one.
+
+In incremental mode,
+the function returns @true if the step finished a collection cycle.
+In generational mode,
 the function returns @true if the step performed a major collection.
 }
 
@@ -6382,13 +6395,9 @@ The argument @id{param} must have one of the following values:
 @item{@St{stepmul}| The step multiplier. }
 @item{@St{stepsize}| The step size. }
 }
-To be able to divide by 100
-(as most parameters are given as percentages)
-without using floating-point arithmetic,
-Lua stores these parameters encoded.
-This encoding approximates the real value;
+Lua rounds these values before storing them;
 so, the value returned as the previous value may not be
-equal to the last value set.
+exactly the last value set.
 }
 
 }

+ 2 - 0
testes/files.lua

@@ -74,6 +74,8 @@ io.input(io.stdin); io.output(io.stdout);
 
 os.remove(file)
 assert(not loadfile(file))
+-- Lua code cannot use chunks with fixed buffers
+checkerr("invalid mode", load, "", "", "B")
 checkerr("", dofile, file)
 assert(not io.open(file))
 io.output(file)

+ 28 - 1
testes/gc.lua

@@ -35,7 +35,7 @@ do
     collectgarbage("setparam", "pause", t[i])
     for j = 1, #t do
       collectgarbage("setparam", "stepmul", t[j])
-      collectgarbage("step")
+      collectgarbage("step", t[j])
     end
   end
   -- restore original parameters
@@ -45,6 +45,33 @@ do
 end
 
 
+--
+-- test the "size" of basic GC steps (whatever they mean...)
+--
+do  print("steps")
+
+  local function dosteps (siz)
+    collectgarbage()
+    local a = {}
+    for i=1,100 do a[i] = {{}}; local b = {} end
+    local x = gcinfo()
+    local i = 0
+    repeat   -- do steps until it completes a collection cycle
+      i = i+1
+    until collectgarbage("step", siz)
+    assert(gcinfo() < x)
+    return i    -- number of steps
+  end
+
+  collectgarbage"stop"
+
+  if not _port then
+    assert(dosteps(10) < dosteps(2))
+  end
+
+end
+
+
 _G["while"] = 234