Why gc sweepstep() doesn't return the real free bytes?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Why gc sweepstep() doesn't return the real free bytes?

张伟智
Lua version 5.3.0
In each gc step,
luaC_step() call singlestep() in while loop until debt reduce to -GCSTEPSIZE,

singlestep() return the bytes haved processed:
1.in propagate state, it return the bytes traversed(marked);
2.in sweep state, it return a estimate value: GCSWEEPMAX * GCSWEEPCOST;

In a 64bits Debian Linux system, GCSWEEPCOST is 7 bytes,
which is much smaller than any kind GCObject(TString, Udata, ...).
After each call to singlestep(), debt reduce GCSWEEPMAX * GCSWEEPCOST,
until to -GCSTEPSIZE.
So the GCSWEEPCOST much smaller,
the times of execute singlestep() is much more,
i.e., the speed of sweep(free) is much faster;

In our program, collectgarbage("count") is 10G at the end of propagate state,
while gc switch to sweep state, gc system free 5G bytes in only 30 seconds,
and the usage of CPU is 99.9% during the whole 30 seconds sweep state;

If I adjust GCSWEEPCOST to a larger value,
the time of sweep state becomes long,
and CPU's usage becomes lower.
But it is a little difficult to adjust GCSWEEPCOST to a fit value;

I am curious about why sweepstep() doesn't return the real free bytes, i.e, olddebt - g->GCdebt ?
Thanks.

1011 static lu_mem sweepstep (lua_State *L, global_State *g,
1012                          int nextstate, GCObject **nextlist) {
1013         if (g->sweepgc) {
1014                 l_mem olddebt = g->GCdebt;
1015                 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1016                 g->GCestimate += g->GCdebt - olddebt;  /* update estimate */
1017                 if (g->sweepgc)  /* is there still something to sweep? */
1018                         return (GCSWEEPMAX * GCSWEEPCOST);
1019         }
             ...
     }

1109 void luaC_step (lua_State *L) {
1110         global_State *g = G(L);
1111         l_mem debt = getdebt(g);  /* GC deficit (be paid now) */
1112         if (!g->gcrunning) {  /* not running? */
1113                 luaE_setdebt(g, -GCSTEPSIZE * 10);  /* avoid being called too often */
1114                 return;
1115         }
1116         do {  /* repeat until pause or enough "credit" (negative debt) */
1117                 lu_mem work = singlestep(L);  /* perform one single step */
1118                 debt -= work;
1119         } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
1120         if (g->gcstate == GCSpause)
1121                 setpause(g);  /* pause until next cycle */
1122         else {
1123                 debt = (debt / g->gcstepmul) * STEPMULADJ;  /* convert 'work units' to Kb */
1124                 luaE_setdebt(g, debt);
1125                 runafewfinalizers(L);
1126         }

1127 }


Best Regards
John Wei
Reply | Threaded
Open this post in threaded view
|

Re: Why gc sweepstep() doesn't return the real free bytes?

Roberto Ierusalimschy
> If I adjust GCSWEEPCOST to a larger value,
> the time of sweep state becomes long,
> and CPU's usage becomes lower.
> But it is a little difficult to adjust GCSWEEPCOST to a fit value;
>
> I am curious about why sweepstep() doesn't return the real free bytes, i.e, olddebt - g->GCdebt ?

In most (all?) systems, the time to free a block does not depend on its
size. More important, we waste time doing a sweep even if we do not
release any memory. So, I do not see why the measure of "work" done
during a sweep should be related to how much memory was freed.
(We could use the size of object being sweeped, but that increases the
work done during a sweep, and again, the time to sweep an object does
not depend on its size.)

That said, all these constants (like GCSWEEPCOST, STEPMULADJ) are rough
guesses, and substantiated suggestions for better values are more
than welcome.


> In our program, collectgarbage("count") is 10G at the end of propagate state,
> while gc switch to sweep state, gc system free 5G bytes in only 30 seconds,
> and the usage of CPU is 99.9% during the whole 30 seconds sweep state;

Is that a problem? Is your program too slow during that period? If you
just feel the sweep is too fast, you can compensate it by setting a
longer pause after the sweep.

-- Roberto


Reply | Threaded
Open this post in threaded view
|

Re: Why gc sweepstep() doesn't return the real free bytes?

张伟智
In reply to this post by 张伟智
At 2015-12-19 02:57:41, "Roberto Ierusalimschy" <[hidden email]> wrote:

>> If I adjust GCSWEEPCOST to a larger value,
>> the time of sweep state becomes long,
>> and CPU's usage becomes lower.
>> But it is a little difficult to adjust GCSWEEPCOST to a fit value;
>>
>> I am curious about why sweepstep() doesn't return the real free bytes, i.e, olddebt - g->GCdebt ?
>
>In most (all?) systems, the time to free a block does not depend on its
>size. More important, we waste time doing a sweep even if we do not
>release any memory. So, I do not see why the measure of "work" done
>during a sweep should be related to how much memory was freed.
>(We could use the size of object being sweeped, but that increases the
>work done during a sweep, and again, the time to sweep an object does
>not depend on its size.)
>
>That said, all these constants (like GCSWEEPCOST, STEPMULADJ) are rough
>guesses, and substantiated suggestions for better values are more
>than welcome.
>
>
>> In our program, collectgarbage("count") is 10G at the end of propagate state,
>> while gc switch to sweep state, gc system free 5G bytes in only 30 seconds,
>> and the usage of CPU is 99.9% during the whole 30 seconds sweep state;
>
>Is that a problem? Is your program too slow during that period? If you
>just feel the sweep is too fast, you can compensate it by setting a
>longer pause after the sweep.
>
>-- Roberto

My program is a MMORPG(massively multiplayer online role-playing game) server.
It sometimes has 10 thousands players online.
You can think of it as a half real-time system.
I hope the delay time of player's operation can be low,
and the CPU's usage is  smooth  in all the time.
In propagate state, it is OK.
But in sweep state, the delay time increases obviously.
It usually take a few seconds for player to see the menu content after click the menu on client.
This is boring.
Actually, I set the "setpause" value to a small value to avoid the memory usage increase to a large value,
once the memory usage increase , the total execute time of atomic() function becomes long,
it will also increase the delay time of player's operation.

Whether it is a solution to change the sweepstep() to return the real free bytes,
so the CPU's usage is smooth in sweep state  like the propagate state.

Thanks.

Best Regards
John Wei
Reply | Threaded
Open this post in threaded view
|

Re: Why gc sweepstep() doesn't return the real free bytes?

Roberto Ierusalimschy
> I hope the delay time of player's operation can be low,
> and the CPU's usage is  smooth  in all the time.
> In propagate state, it is OK.
> But in sweep state, the delay time increases obviously.
> It usually take a few seconds for player to see the menu content after click the menu on client.
> This is boring.
> Actually, I set the "setpause" value to a small value to avoid the memory usage increase to a large value,
> once the memory usage increase , the total execute time of atomic() function becomes long,
> it will also increase the delay time of player's operation.
>
> Whether it is a solution to change the sweepstep() to return the real free bytes,
> so the CPU's usage is smooth in sweep state  like the propagate state.

What happens if you increase GCSWEEPCOST (and maybe reduce even more the
pause)?

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Why gc sweepstep() doesn't return the real free bytes?

张伟智
In reply to this post by 张伟智

At 2015-12-19 21:30:52, "Roberto Ierusalimschy" <[hidden email]> wrote:

>> I hope the delay time of player's operation can be low,
>> and the CPU's usage is  smooth  in all the time.
>> In propagate state, it is OK.
>> But in sweep state, the delay time increases obviously.
>> It usually take a few seconds for player to see the menu content after click the menu on client.
>> This is boring.
>> Actually, I set the "setpause" value to a small value to avoid the memory usage increase to a large value,
>> once the memory usage increase , the total execute time of atomic() function becomes long,
>> it will also increase the delay time of player's operation.
>>
>> Whether it is a solution to change the sweepstep() to return the real free bytes,
>> so the CPU's usage is smooth in sweep state  like the propagate state.
>
>What happens if you increase GCSWEEPCOST (and maybe reduce even more the
>pause)?
>
>-- Roberto

If I increase GCSWEEPCOST and set the "setpause" value to a smal value(60),
the total time of sweep state becomes long(about 7 minutes  VS 30 seconds of the default GCSWEEPCOST),‍
during the 7 minutes, the average CPU's usage is  lower than ‍the usage on default GCSWEEPCOST setting,
but not smooth, the CPU's usage sometimes increases to a high value,  and decrease after a few seconds,

Oppositely, the total time of propagate state becomes short(about 1 minutes),
the CPU's usage is smooth during the whole propagate state.

Thanks.

Best Regards
John Wei