Several tweaks in the garbage collector
- back with step size in collectgarbage("step")
- adjustments in defaults for some GC parameters
- adjustments in 'luaO_codeparam'
This commit is contained in:
18
lapi.c
18
lapi.c
@@ -416,10 +416,11 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
|
|||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
o = index2value(L, idx); /* previous call may reallocate the stack */
|
o = index2value(L, idx); /* previous call may reallocate the stack */
|
||||||
}
|
}
|
||||||
if (len != NULL)
|
|
||||||
*len = tsslen(tsvalue(o));
|
|
||||||
lua_unlock(L);
|
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: {
|
case LUA_GCSTEP: {
|
||||||
lu_byte oldstp = g->gcstp;
|
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) */
|
g->gcstp = 0; /* allow GC to run (other bits must be zero here) */
|
||||||
luaC_step(L); /* run one basic step */
|
if (n <= 0)
|
||||||
g->gcstp = oldstp; /* restore previous state */
|
n = g->GCdebt; /* force to run one basic step */
|
||||||
if (g->gcstate == GCSpause) /* end of cycle? */
|
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 */
|
res = 1; /* signal it */
|
||||||
|
g->gcstp = oldstp; /* restore previous state */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_GCISRUNNING: {
|
case LUA_GCISRUNNING: {
|
||||||
|
|||||||
10
lbaselib.c
10
lbaselib.c
@@ -213,7 +213,8 @@ static int luaB_collectgarbage (lua_State *L) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case LUA_GCSTEP: {
|
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);
|
checkvalres(res);
|
||||||
lua_pushboolean(L, res);
|
lua_pushboolean(L, res);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -239,7 +240,7 @@ static int luaB_collectgarbage (lua_State *L) {
|
|||||||
LUA_GCPPAUSE, LUA_GCPSTEPMUL, LUA_GCPSTEPSIZE};
|
LUA_GCPPAUSE, LUA_GCPSTEPMUL, LUA_GCPSTEPSIZE};
|
||||||
int p = pnum[luaL_checkoption(L, 2, NULL, params)];
|
int p = pnum[luaL_checkoption(L, 2, NULL, params)];
|
||||||
lua_Integer value = luaL_checkinteger(L, 3);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
default: {
|
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) {
|
static const char *getmode (lua_State *L, int idx) {
|
||||||
const char *mode = luaL_optstring(L, idx, "bt");
|
const char *mode = luaL_optstring(L, idx, "bt");
|
||||||
int i = 0;
|
if (strchr(mode, 'B') != NULL) /* Lua code cannot use fixed buffers */
|
||||||
if (mode[i] == 'b') i++;
|
|
||||||
if (mode[i] == 't') i++;
|
|
||||||
if (mode[i] != '\0')
|
|
||||||
luaL_argerror(L, idx, "invalid mode");
|
luaL_argerror(L, idx, "invalid mode");
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|||||||
4
lgc.h
4
lgc.h
@@ -171,13 +171,13 @@
|
|||||||
** Major collections will shift to minor ones after a collection
|
** Major collections will shift to minor ones after a collection
|
||||||
** collects at least LUAI_MAJORMINOR% of the new objects.
|
** 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%
|
** A young (minor) collection will run after creating LUAI_GENMINORMUL%
|
||||||
** new objects.
|
** new objects.
|
||||||
*/
|
*/
|
||||||
#define LUAI_GENMINORMUL 20
|
#define LUAI_GENMINORMUL 25
|
||||||
|
|
||||||
|
|
||||||
/* incremental */
|
/* incremental */
|
||||||
|
|||||||
18
lobject.c
18
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
|
** The exponent is represented using excess-7. Mimicking IEEE 754, the
|
||||||
** representation normalizes the number when possible, assuming an extra
|
** representation normalizes the number when possible, assuming an extra
|
||||||
** 1 before the mantissa (xxx) and adding one to the exponent (eeeeexxx)
|
** 1 before the mantissa (xxxx) and adding one to the exponent (eeee)
|
||||||
** to signal that. So, the real value is (1xxx) * 2^(eeeee - 8) if
|
** to signal that. So, the real value is (1xxxx) * 2^(eeee - 7 - 1) if
|
||||||
** eeeee != 0, and (xxx) * 2^-7 otherwise.
|
** eeee != 0, and (xxxx) * 2^-7 otherwise (subnormal numbers).
|
||||||
*/
|
*/
|
||||||
unsigned int luaO_codeparam (unsigned int p) {
|
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 */
|
return 0xFF; /* return maximum value */
|
||||||
else {
|
else {
|
||||||
p = (p * 128u) / 100;
|
p = (cast(l_uint32, p) * 128 + 99) / 100; /* round up the division */
|
||||||
if (p <= 0xF)
|
if (p < 0x10) /* subnormal number? */
|
||||||
return p;
|
return p; /* exponent bits are already zero; nothing else to do */
|
||||||
else {
|
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);
|
return ((p >> log) - 0x10) | ((log + 1) << 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -427,8 +427,8 @@ typedef struct TString {
|
|||||||
** Get string and length */
|
** Get string and length */
|
||||||
#define getlstr(ts, len) \
|
#define getlstr(ts, len) \
|
||||||
(strisshr(ts) \
|
(strisshr(ts) \
|
||||||
? (cast_void(len = (ts)->shrlen), rawgetshrstr(ts)) \
|
? (cast_void((len) = (ts)->shrlen), rawgetshrstr(ts)) \
|
||||||
: (cast_void(len = (ts)->u.lnglen), (ts)->contents))
|
: (cast_void((len) = (ts)->u.lnglen), (ts)->contents))
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|||||||
@@ -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 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 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
|
The garbage-collector step size controls the
|
||||||
size of each incremental step,
|
size of each incremental step,
|
||||||
specifically how many objects the interpreter creates
|
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.
|
approximately @M{n} objects between steps.
|
||||||
The default value is 250.
|
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}
|
@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.
|
The minor multiplier controls the frequency of minor collections.
|
||||||
For a minor multiplier @M{x},
|
For a minor multiplier @M{x},
|
||||||
a new minor collection will be done when the number of objects
|
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,
|
For instance, for a multiplier of 20,
|
||||||
the collector will do a minor collection when the number of objects
|
the collector will do a minor collection when the number of objects
|
||||||
gets 20% larger than the total after the last major collection.
|
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.
|
The minor-major multiplier controls the shift to major collections.
|
||||||
For a multiplier @M{x},
|
For a multiplier @M{x},
|
||||||
@@ -728,11 +728,10 @@ For a multiplier @M{x},
|
|||||||
the collector will shift back to minor collections
|
the collector will shift back to minor collections
|
||||||
after a major collection collects at least @M{x%}
|
after a major collection collects at least @M{x%}
|
||||||
of the objects allocated during the last cycle.
|
of the objects allocated during the last cycle.
|
||||||
|
|
||||||
In particular, for a multiplier of 0,
|
In particular, for a multiplier of 0,
|
||||||
the collector will immediately shift back to minor collections
|
the collector will immediately shift back to minor collections
|
||||||
after doing one cycle of major 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.
|
memory in use by Lua by 1024.
|
||||||
}
|
}
|
||||||
|
|
||||||
@item{@defid{LUA_GCSTEP}|
|
@item{@defid{LUA_GCSTEP} (int n)|
|
||||||
Performs a step of garbage collection.
|
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.
|
the reader function should return the entire chunk in the first read.
|
||||||
(As an example, @Lid{luaL_loadbufferx} does that.)
|
(As an example, @Lid{luaL_loadbufferx} does that.)
|
||||||
|
|
||||||
@id{lua_load} uses the stack internally,
|
The function @Lid{lua_load} fully preserves the Lua stack
|
||||||
so the reader function must always leave the stack
|
through the calls to the reader function,
|
||||||
unmodified when returning.
|
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
|
@id{lua_load} can return
|
||||||
@Lid{LUA_OK}, @Lid{LUA_ERRSYNTAX}, or @Lid{LUA_ERRMEM}.
|
@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}|
|
@item{@St{step}|
|
||||||
Performs a garbage-collection 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,
|
||||||
|
a basic step corresponds to the current step size.
|
||||||
|
In generational mode,
|
||||||
|
a basic step performs a full minor collection or
|
||||||
|
a major collection,
|
||||||
|
if the collector has scheduled one.
|
||||||
|
|
||||||
In incremental mode,
|
In incremental mode,
|
||||||
that step corresponds to the current step size;
|
|
||||||
the function returns @true if the step finished a collection cycle.
|
the function returns @true if the step finished a collection cycle.
|
||||||
In generational mode,
|
In generational mode,
|
||||||
the step performs a full minor collection or
|
|
||||||
a major collection,
|
|
||||||
if the collector has scheduled one;
|
|
||||||
the function returns @true if the step performed a major collection.
|
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{stepmul}| The step multiplier. }
|
||||||
@item{@St{stepsize}| The step size. }
|
@item{@St{stepsize}| The step size. }
|
||||||
}
|
}
|
||||||
To be able to divide by 100
|
Lua rounds these values before storing them;
|
||||||
(as most parameters are given as percentages)
|
|
||||||
without using floating-point arithmetic,
|
|
||||||
Lua stores these parameters encoded.
|
|
||||||
This encoding approximates the real value;
|
|
||||||
so, the value returned as the previous value may not be
|
so, the value returned as the previous value may not be
|
||||||
equal to the last value set.
|
exactly the last value set.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ io.input(io.stdin); io.output(io.stdout);
|
|||||||
|
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
assert(not loadfile(file))
|
assert(not loadfile(file))
|
||||||
|
-- Lua code cannot use chunks with fixed buffers
|
||||||
|
checkerr("invalid mode", load, "", "", "B")
|
||||||
checkerr("", dofile, file)
|
checkerr("", dofile, file)
|
||||||
assert(not io.open(file))
|
assert(not io.open(file))
|
||||||
io.output(file)
|
io.output(file)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ do
|
|||||||
collectgarbage("setparam", "pause", t[i])
|
collectgarbage("setparam", "pause", t[i])
|
||||||
for j = 1, #t do
|
for j = 1, #t do
|
||||||
collectgarbage("setparam", "stepmul", t[j])
|
collectgarbage("setparam", "stepmul", t[j])
|
||||||
collectgarbage("step")
|
collectgarbage("step", t[j])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- restore original parameters
|
-- restore original parameters
|
||||||
@@ -45,6 +45,33 @@ do
|
|||||||
end
|
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
|
_G["while"] = 234
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user