aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2012-05-28 17:41:00 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2012-05-28 17:41:00 -0300
commit51e8f08e609b20af6f70641855d9be5edb2f1328 (patch)
tree53225bf78b0a37cd79b08186ff4666e5cbd5f3d5 /lgc.c
parent5adb5a4812f1894a70650e7529808968c522de9d (diff)
downloadlua-51e8f08e609b20af6f70641855d9be5edb2f1328.tar.gz
lua-51e8f08e609b20af6f70641855d9be5edb2f1328.tar.bz2
lua-51e8f08e609b20af6f70641855d9be5edb2f1328.zip
more efficient way to apply 'stepmul' + some changes in GC parameters
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/lgc.c b/lgc.c
index fc888d04..64e8df97 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.127 2012/05/22 18:38:56 roberto Exp roberto $ 2** $Id: lgc.c,v 2.128 2012/05/23 15:43:14 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -24,8 +24,11 @@
24 24
25 25
26 26
27/* cost of sweeping one element (half the size of a small object) */ 27/*
28#define GCSWEEPCOST ((sizeof(TString) + 4) / 2) 28** cost of sweeping one element (the size of a small object divided
29** by some adjust for the sweep speed)
30*/
31#define GCSWEEPCOST ((sizeof(TString) + 4) / 4)
29 32
30/* maximum number of elements to sweep in each single step */ 33/* maximum number of elements to sweep in each single step */
31#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) 34#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
@@ -33,25 +36,27 @@
33/* maximum number of finalizers to call in each GC step */ 36/* maximum number of finalizers to call in each GC step */
34#define GCFINALIZENUM 4 37#define GCFINALIZENUM 4
35 38
36/* (arbitrary) cost of atomic step */
37#define GCATOMICCOST GCSTEPSIZE
38 39
40/*
41** macro to adjust 'stepmul': 'stepmul' is actually used like
42** 'stepmul / STEPMULADJ' (value chosen by tests)
43*/
44#define STEPMULADJ 200
39 45
40/* 46/*
41** macro to apply the "speed" of the garbage collector: the constant 47** macro to adjust 'pause': 'pause' is actually used like
42** 80 makes the standard 'stepmul' of 200 results in the GC handling 48** 'pause / PAUSEADJ' (value chosen by tests)
43** 80/200 = 1/2.5 = 0.4Kbytes for every 1Kb allocated.
44** (The computation tries to avoid overflows or underflows.)
45*/ 49*/
46#define workrate(x,mul) \ 50#define PAUSEADJ 200
47 ((x) < MAX_INT/80 ? ((x) * 80) / mul : ((x) / mul) * 80) 51
52
48 53
49 54
50/* 55/*
51** standard negative debt for GC; a reasonable "time" to wait before 56** standard negative debt for GC; a reasonable "time" to wait before
52** starting a new cycle 57** starting a new cycle
53*/ 58*/
54#define stddebtest(g,e) (-cast(l_mem, (e)/100) * g->gcpause) 59#define stddebtest(g,e) (-cast(l_mem, (e)/PAUSEADJ) * g->gcpause)
55#define stddebt(g) stddebtest(g, gettotalbytes(g)) 60#define stddebt(g) stddebtest(g, gettotalbytes(g))
56 61
57 62
@@ -672,7 +677,7 @@ static void freeobj (lua_State *L, GCObject *o) {
672 case LUA_TTABLE: luaH_free(L, gco2t(o)); break; 677 case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
673 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; 678 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
674 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; 679 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
675 case LUA_TSHRSTR: 680 case LUA_TSHRSTR:
676 G(L)->strt.nuse--; 681 G(L)->strt.nuse--;
677 /* go through */ 682 /* go through */
678 case LUA_TLNGSTR: { 683 case LUA_TLNGSTR: {
@@ -955,8 +960,9 @@ void luaC_freeallobjects (lua_State *L) {
955} 960}
956 961
957 962
958static void atomic (lua_State *L) { 963static l_mem atomic (lua_State *L) {
959 global_State *g = G(L); 964 global_State *g = G(L);
965 l_mem trav = g->GCmemtrav;
960 GCObject *origweak, *origall; 966 GCObject *origweak, *origall;
961 lua_assert(!iswhite(obj2gco(g->mainthread))); 967 lua_assert(!iswhite(obj2gco(g->mainthread)));
962 markobject(g, L); /* mark running thread */ 968 markobject(g, L); /* mark running thread */
@@ -976,6 +982,7 @@ static void atomic (lua_State *L) {
976 separatetobefnz(L, 0); /* separate objects to be finalized */ 982 separatetobefnz(L, 0); /* separate objects to be finalized */
977 markbeingfnz(g); /* mark userdata that will be finalized */ 983 markbeingfnz(g); /* mark userdata that will be finalized */
978 propagateall(g); /* remark, to propagate `preserveness' */ 984 propagateall(g); /* remark, to propagate `preserveness' */
985 trav = g->GCmemtrav - trav; /* avoid adding convergence twice */
979 convergeephemerons(g); 986 convergeephemerons(g);
980 /* at this point, all resurrected objects are marked. */ 987 /* at this point, all resurrected objects are marked. */
981 /* remove dead objects from weak tables */ 988 /* remove dead objects from weak tables */
@@ -987,6 +994,7 @@ static void atomic (lua_State *L) {
987 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 994 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
988 entersweep(L); /* prepare to sweep strings */ 995 entersweep(L); /* prepare to sweep strings */
989 /*lua_checkmemory(L);*/ 996 /*lua_checkmemory(L);*/
997 return trav; /* reasonable estimate of the work done by 'atomic' */
990} 998}
991 999
992 1000
@@ -1012,8 +1020,7 @@ static lu_mem singlestep (lua_State *L) {
1012 else { /* no more `gray' objects */ 1020 else { /* no more `gray' objects */
1013 g->gcstate = GCSatomic; /* finish mark phase */ 1021 g->gcstate = GCSatomic; /* finish mark phase */
1014 g->GCestimate = g->GCmemtrav; /* save what was counted */ 1022 g->GCestimate = g->GCmemtrav; /* save what was counted */
1015 atomic(L); 1023 return atomic(L);
1016 return GCATOMICCOST;
1017 } 1024 }
1018 } 1025 }
1019 case GCSsweepstring: { 1026 case GCSsweepstring: {
@@ -1086,14 +1093,18 @@ static void step (lua_State *L) {
1086 global_State *g = G(L); 1093 global_State *g = G(L);
1087 l_mem debt = g->GCdebt; 1094 l_mem debt = g->GCdebt;
1088 int stepmul = g->gcstepmul; 1095 int stepmul = g->gcstepmul;
1089 if (stepmul <= 0) stepmul = 1; 1096 if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values */
1097 /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */
1098 debt = (debt / STEPMULADJ) + 1;
1099 debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
1090 do { /* always perform at least one single step */ 1100 do { /* always perform at least one single step */
1091 lu_mem work = singlestep(L); /* do some work */ 1101 lu_mem work = singlestep(L); /* do some work */
1092 work = workrate(work, stepmul); /* apply work rate */
1093 debt -= work; 1102 debt -= work;
1094 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); 1103 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
1095 if (g->gcstate == GCSpause) 1104 if (g->gcstate == GCSpause)
1096 debt = stddebtest(g, g->GCestimate); /* pause until next cycle */ 1105 debt = stddebtest(g, g->GCestimate); /* pause until next cycle */
1106 else
1107 debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */
1097 luaE_setdebt(g, debt); 1108 luaE_setdebt(g, debt);
1098} 1109}
1099 1110