浏览代码

Revamp of GC parameters

More uniformity when handling GC parameters + avoid divisions by 100
when applying them.
Roberto Ierusalimschy 2 年之前
父节点
当前提交
40565b4a08
共有 6 个文件被更改,包括 61 次插入41 次删除
  1. 15 15
      lapi.c
  2. 5 9
      lgc.c
  3. 34 10
      lgc.h
  4. 1 1
      llimits.h
  5. 4 4
      lstate.c
  6. 2 2
      ltests.c

+ 15 - 15
lapi.c

@@ -1185,15 +1185,15 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
       break;
     }
     case LUA_GCSETPAUSE: {
-      int data = va_arg(argp, int);
-      res = getgcparam(g->gcpause);
-      setgcparam(g->gcpause, data);
+      unsigned int data = va_arg(argp, unsigned int);
+      res = applygcparam(g, gcpause, 100);
+      setgcparam(g, gcpause, data);
       break;
     }
     case LUA_GCSETSTEPMUL: {
-      int data = va_arg(argp, int);
-      res = getgcparam(g->gcstepmul);
-      setgcparam(g->gcstepmul, data);
+      unsigned int data = va_arg(argp, unsigned int);
+      res = applygcparam(g, gcstepmul, 100);
+      setgcparam(g, gcstepmul, data);
       break;
     }
     case LUA_GCISRUNNING: {
@@ -1201,25 +1201,25 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
       break;
     }
     case LUA_GCGEN: {
-      int minormul = va_arg(argp, int);
-      int majormul = va_arg(argp, int);
+      unsigned int minormul = va_arg(argp, unsigned int);
+      unsigned int majormul = va_arg(argp, unsigned int);
       res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
       if (minormul != 0)
-        g->genminormul = minormul;
+        setgcparam(g, genminormul, minormul);
       if (majormul != 0)
-        setgcparam(g->genmajormul, majormul);
+        setgcparam(g, genmajormul, majormul);
       luaC_changemode(L, KGC_GEN);
       break;
     }
     case LUA_GCINC: {
-      int pause = va_arg(argp, int);
-      int stepmul = va_arg(argp, int);
-      int stepsize = va_arg(argp, int);
+      unsigned int pause = va_arg(argp, unsigned int);
+      unsigned int stepmul = va_arg(argp, unsigned int);
+      unsigned int stepsize = va_arg(argp, unsigned int);
       res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN;
       if (pause != 0)
-        setgcparam(g->gcpause, pause);
+        setgcparam(g, gcpause, pause);
       if (stepmul != 0)
-        setgcparam(g->gcstepmul, stepmul);
+        setgcparam(g, gcstepmul, stepmul);
       if (stepsize != 0)
         g->gcstepsize = (stepsize <= log2maxs(l_obj)) ? stepsize
                                                       : log2maxs(l_obj);

+ 5 - 9
lgc.c

@@ -1030,14 +1030,10 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
 /*
 ** Set the "time" to wait before starting a new GC cycle; cycle will
 ** start when number of objects in use hits the threshold of
-** approximately ('marked' * pause / 100). (A direct multiplication
-** by 'pause' may overflow, and a direct division by 100 may undeflow
-** to zero. So, the division is done in two steps. 8 * 12 is near 100
-** and the division by 8 is cheap.)
+** approximately (marked * pause / 100).
 */
 static void setpause (global_State *g) {
-  unsigned int pause = getgcparam(g->gcpause);
-  l_obj threshold = g->marked / 8 * pause / 12;
+  l_obj threshold = applygcparam(g, gcpause, g->marked);
   l_obj debt = gettotalobjs(g) - threshold;
   if (debt > 0) debt = 0;
   luaE_setdebt(g, debt);
@@ -1289,7 +1285,7 @@ static void atomic2gen (lua_State *L, global_State *g) {
 ** total number of objects grows 'genminormul'%.
 */
 static void setminordebt (global_State *g) {
-  luaE_setdebt(g, -(gettotalobjs(g) / 100) * g->genminormul);
+  luaE_setdebt(g, -applygcparam(g, genminormul, gettotalobjs(g)));
 }
 
 
@@ -1387,7 +1383,7 @@ static void genmajorstep (lua_State *L, global_State *g) {
 */
 static void genstep (lua_State *L, global_State *g) {
   l_obj majorbase = g->GClastmajor;  /* count after last major collection */
-  l_obj majorinc = (majorbase / 100) * getgcparam(g->genmajormul);
+  l_obj majorinc = applygcparam(g, genmajormul, majorbase);
   if (g->GCdebt > 0 && gettotalobjs(g) > majorbase + majorinc) {
     /* do a major collection */
     enterinc(g);
@@ -1601,7 +1597,7 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
 */
 static void incstep (lua_State *L, global_State *g) {
   l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
-  l_obj work2do = stepsize * getgcparam(g->gcstepmul) / 100;
+  l_obj work2do = applygcparam(g, gcstepmul, stepsize);
   do {  /* repeat until pause or enough "credit" (negative debt) */
     l_obj work = singlestep(L);  /* perform one single step */
     work2do -= work;

+ 34 - 10
lgc.h

@@ -8,6 +8,9 @@
 #define lgc_h
 
 
+#include <stddef.h>
+
+
 #include "lobject.h"
 #include "lstate.h"
 
@@ -122,20 +125,18 @@
 
 
 /* Default Values for GC parameters */
-#define LUAI_GENMAJORMUL         100
-#define LUAI_GENMINORMUL         20
+
+/* generational */
+
+#define LUAI_GENMAJORMUL         100	/* major multiplier */
+#define LUAI_GENMINORMUL         20	/* minor multiplier */
+
+/* incremental */
 
 /* wait memory to double before starting new cycle */
 #define LUAI_GCPAUSE    200
 
-/*
-** some gc parameters are stored divided by 4 to allow a maximum value
-** up to 1023 in a 'lu_byte'.
-*/
-#define getgcparam(p)	((p) * 4)
-#define setgcparam(p,v)	((p) = (v) / 4)
-
-#define LUAI_GCMUL      300
+#define LUAI_GCMUL      300	/* step multiplier */
 
 /* how many objects to allocate before next GC step (log2) */
 #define LUAI_GCSTEPSIZE 8      /* 256 objects */
@@ -149,6 +150,29 @@
 #define GCSTPCLS	4  /* bit true when closing Lua state */
 #define gcrunning(g)	((g)->gcstp == 0)
 
+/*
+** Macros to set and apply GC parameters. GC parameters are given in
+** percentage points, but are stored as lu_byte. To reduce their
+** values and avoid repeated divisions by 100, these macros store
+** the original parameter multiplied by 2^n and divided by 100.
+** To apply them, the value is divided by 2^n (a shift) and then
+** multiplied by the stored parameter, yielding
+** value / 2^n * (original parameter * 2^n / 100), or approximately
+** (value * original parameter / 100).
+**
+** For most parameters, which are typically larger than 100%, 2^n is
+** 16 (2^4), allowing maximum values up to 1599.  For the minor
+** multiplier, which is typically smaller, 2^n is 64 (2^6) to allow more
+** precision.
+*/
+#define gcparamshift(p)  \
+  (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4)
+
+#define setgcparam(g,p,v)  \
+	(g->p = (cast_uint(v) << gcparamshift(p)) / 100u)
+#define applygcparam(g,p,v)	(((v) >> gcparamshift(p)) * g->p)
+
+
 
 /*
 ** Does one step of collection when debt becomes positive. 'pre'/'pos'

+ 1 - 1
llimits.h

@@ -18,7 +18,7 @@
 /*
 ** 'lu_mem' is an unsigned integer big enough to count the total memory
 ** used by Lua (in bytes). 'l_obj' is a signed integer big enough to
-** count the total number of objects used by Lua. (It is negative due
+** count the total number of objects used by Lua. (It is signed due
 ** to the use of debt in several computations.)  Usually, 'size_t' and
 ** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
 */

+ 4 - 4
lstate.c

@@ -392,11 +392,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->marked = 0;
   g->GCdebt = 0;
   setivalue(&g->nilvalue, 0);  /* to signal that state is not yet built */
-  setgcparam(g->gcpause, LUAI_GCPAUSE);
-  setgcparam(g->gcstepmul, LUAI_GCMUL);
+  setgcparam(g, gcpause, LUAI_GCPAUSE);
+  setgcparam(g, gcstepmul, LUAI_GCMUL);
   g->gcstepsize = LUAI_GCSTEPSIZE;
-  setgcparam(g->genmajormul, LUAI_GENMAJORMUL);
-  g->genminormul = LUAI_GENMINORMUL;
+  setgcparam(g, genmajormul, LUAI_GENMAJORMUL);
+  setgcparam(g, genminormul, LUAI_GENMINORMUL);
   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
     /* memory allocation error: free partial state */

+ 2 - 2
ltests.c

@@ -1031,8 +1031,8 @@ static int query_inc (lua_State *L) {
   global_State *g = G(L);
   lua_pushinteger(L, gettotalobjs(g));
   lua_pushinteger(L, g->GCdebt);
-  lua_pushinteger(L, getgcparam(g->gcpause));
-  lua_pushinteger(L, getgcparam(g->gcstepmul));
+  lua_pushinteger(L, applygcparam(g, gcpause, 100));
+  lua_pushinteger(L, applygcparam(g, gcstepmul, 100));
   lua_pushinteger(L, cast(l_obj, 1) << g->gcstepsize);
   return 5;
 }