diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-05-28 17:41:00 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-05-28 17:41:00 -0300 |
commit | 51e8f08e609b20af6f70641855d9be5edb2f1328 (patch) | |
tree | 53225bf78b0a37cd79b08186ff4666e5cbd5f3d5 /lgc.c | |
parent | 5adb5a4812f1894a70650e7529808968c522de9d (diff) | |
download | lua-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.c | 47 |
1 files changed, 29 insertions, 18 deletions
@@ -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 | ||
958 | static void atomic (lua_State *L) { | 963 | static 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 | ||