diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-01 11:06:59 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-04-01 11:06:59 -0300 |
commit | 0d745ed04c93e907e9f2bd8c21ce1ca27bba9b6a (patch) | |
tree | 757457a8f20976bb4695c65e7904396c888319b2 /lgc.c | |
parent | 3d1c6730daac6d2d0f33f3ed2372c235b6cf5286 (diff) | |
download | lua-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.c | 32 |
1 files changed, 18 insertions, 14 deletions
@@ -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 | */ |
778 | static void checkSizes (lua_State *L, global_State *g) { | 778 | static 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 | */ |
921 | static void setpause (global_State *g, l_mem estimate) { | 922 | static 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) { | |||
1008 | static lu_mem sweepstep (lua_State *L, global_State *g, | 1009 | static 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 | } |