summaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-04-01 11:06:59 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2014-04-01 11:06:59 -0300
commit0d745ed04c93e907e9f2bd8c21ce1ca27bba9b6a (patch)
tree757457a8f20976bb4695c65e7904396c888319b2 /lgc.c
parent3d1c6730daac6d2d0f33f3ed2372c235b6cf5286 (diff)
downloadlua-0d745ed04c93e907e9f2bd8c21ce1ca27bba9b6a.tar.gz
lua-0d745ed04c93e907e9f2bd8c21ce1ca27bba9b6a.tar.bz2
lua-0d745ed04c93e907e9f2bd8c21ce1ca27bba9b6a.zip
more precise estimation (GCestimate) for total bytes in use after
a GC cycle
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/lgc.c b/lgc.c
index 537c38fe..348781c0 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.178 2014/02/19 13:51:09 roberto Exp roberto $ 2** $Id: lgc.c,v 2.179 2014/03/21 13:52:33 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*/
@@ -777,9 +777,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
777*/ 777*/
778static void checkSizes (lua_State *L, global_State *g) { 778static void checkSizes (lua_State *L, global_State *g) {
779 if (g->gckind != KGC_EMERGENCY) { 779 if (g->gckind != KGC_EMERGENCY) {
780 l_mem olddebt = g->GCdebt;
780 luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ 781 luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
781 if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ 782 if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
782 luaS_resize(L, g->strt.size / 2); /* shrink it a little */ 783 luaS_resize(L, g->strt.size / 2); /* shrink it a little */
784 g->GCestimate += g->GCdebt - olddebt; /* update estimate */
783 } 785 }
784} 786}
785 787
@@ -888,18 +890,17 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
888 return; /* nothing to be done */ 890 return; /* nothing to be done */
889 else { /* move 'o' to 'finobj' list */ 891 else { /* move 'o' to 'finobj' list */
890 GCObject **p; 892 GCObject **p;
891 if (g->sweepgc == &o->gch.next) { /* avoid removing current sweep object */ 893 if (issweepphase(g)) {
892 lua_assert(issweepphase(g)); 894 makewhite(g, o); /* "sweep" object 'o' */
893 g->sweepgc = sweeptolive(L, g->sweepgc, NULL); 895 if (g->sweepgc == &o->gch.next) /* shoud not remove 'sweepgc' object */
896 g->sweepgc = sweeptolive(L, g->sweepgc, NULL); /* change 'sweepgc' */
894 } 897 }
895 /* search for pointer pointing to 'o' */ 898 /* search for pointer pointing to 'o' */
896 for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } 899 for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
897 *p = o->gch.next; /* remove 'o' from its list */ 900 *p = o->gch.next; /* remove 'o' from 'allgc' list */
898 o->gch.next = g->finobj; /* link it in "fin" list */ 901 o->gch.next = g->finobj; /* link it in "fin" list */
899 g->finobj = o; 902 g->finobj = o;
900 l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */ 903 l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */
901 if (issweepphase(g))
902 makewhite(g, o); /* "sweep" object */
903 } 904 }
904} 905}
905 906
@@ -918,9 +919,9 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
918** set a reasonable "time" to wait before starting a new GC cycle; 919** set a reasonable "time" to wait before starting a new GC cycle;
919** cycle will start when memory use hits threshold 920** cycle will start when memory use hits threshold
920*/ 921*/
921static void setpause (global_State *g, l_mem estimate) { 922static void setpause (global_State *g) {
922 l_mem threshold, debt; 923 l_mem threshold, debt;
923 estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ 924 l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */
924 threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ 925 threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */
925 ? estimate * g->gcpause /* no overflow */ 926 ? estimate * g->gcpause /* no overflow */
926 : MAX_LMEM; /* overflow; truncate to maximum */ 927 : MAX_LMEM; /* overflow; truncate to maximum */
@@ -1008,7 +1009,9 @@ static l_mem atomic (lua_State *L) {
1008static lu_mem sweepstep (lua_State *L, global_State *g, 1009static lu_mem sweepstep (lua_State *L, global_State *g,
1009 int nextstate, GCObject **nextlist) { 1010 int nextstate, GCObject **nextlist) {
1010 if (g->sweepgc) { 1011 if (g->sweepgc) {
1012 l_mem olddebt = g->GCdebt;
1011 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); 1013 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1014 g->GCestimate += g->GCdebt - olddebt; /* update estimate */
1012 if (g->sweepgc) /* is there still something to sweep? */ 1015 if (g->sweepgc) /* is there still something to sweep? */
1013 return (GCSWEEPMAX * GCSWEEPCOST); 1016 return (GCSWEEPMAX * GCSWEEPCOST);
1014 } 1017 }
@@ -1041,10 +1044,9 @@ static lu_mem singlestep (lua_State *L) {
1041 lu_mem work; 1044 lu_mem work;
1042 int sw; 1045 int sw;
1043 propagateall(g); /* make sure gray list is empty */ 1046 propagateall(g); /* make sure gray list is empty */
1044 g->GCestimate = g->GCmemtrav; /* save what was counted */;
1045 work = atomic(L); /* work is what was traversed by 'atomic' */ 1047 work = atomic(L); /* work is what was traversed by 'atomic' */
1046 g->GCestimate += work; /* estimate of total memory traversed */
1047 sw = entersweep(L); 1048 sw = entersweep(L);
1049 g->GCestimate = gettotalbytes(g); /* first estimate */;
1048 return work + sw * GCSWEEPCOST; 1050 return work + sw * GCSWEEPCOST;
1049 } 1051 }
1050 case GCSswpallgc: { /* sweep "regular" objects */ 1052 case GCSswpallgc: { /* sweep "regular" objects */
@@ -1063,7 +1065,7 @@ static lu_mem singlestep (lua_State *L) {
1063 return 0; 1065 return 0;
1064 } 1066 }
1065 case GCScallfin: { /* state to finish calling finalizers */ 1067 case GCScallfin: { /* state to finish calling finalizers */
1066 /* do nothing here; should be handled by 'luaC_forcestep' */ 1068 /* do nothing here; this state is handled by 'luaC_step' */
1067 g->gcstate = GCSpause; /* finish collection */ 1069 g->gcstate = GCSpause; /* finish collection */
1068 return 0; 1070 return 0;
1069 } 1071 }
@@ -1131,7 +1133,7 @@ void luaC_step (lua_State *L) {
1131 } 1133 }
1132 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); 1134 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
1133 if (g->gcstate == GCSpause) 1135 if (g->gcstate == GCSpause)
1134 setpause(g, g->GCestimate); /* pause until next cycle */ 1136 setpause(g); /* pause until next cycle */
1135 else { 1137 else {
1136 debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ 1138 debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */
1137 luaE_setdebt(g, debt); 1139 luaE_setdebt(g, debt);
@@ -1160,8 +1162,10 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1160 luaC_runtilstate(L, bitmask(GCSpause)); 1162 luaC_runtilstate(L, bitmask(GCSpause));
1161 luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ 1163 luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */
1162 luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ 1164 luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */
1165 /* estimate must be correct after full GC cycles */
1166 lua_assert(g->GCestimate == gettotalbytes(g));
1163 g->gckind = KGC_NORMAL; 1167 g->gckind = KGC_NORMAL;
1164 setpause(g, gettotalbytes(g)); 1168 setpause(g);
1165 if (!isemergency) /* do not run finalizers during emergency GC */ 1169 if (!isemergency) /* do not run finalizers during emergency GC */
1166 callallpendingfinalizers(L, 1); 1170 callallpendingfinalizers(L, 1);
1167} 1171}