• Advertisement
Sign in to follow this  

Lua GC - OK what am I doing wrong?

This topic is 4144 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, I'm using Lua in my game and I'm having some quite serious memory issues with it. Since i've just started out with Lua, there's not really that much going on. Only a few Lua functions are called every frame, but it seems that Lua just keeps allocating more and more memory over time. I'm not doing anything too complicated (only calling a few c-side functions in the per-frame lua function). I use: lua_gc(luaVM, LUA_GCCOUNT, 0); to get the current GC count. I've tried: lua_gc(luaVM, LUA_GCCOLLECT, 0); every frame but my frame rate takes a plunge after only a few minutes as the GC is spending more and more time doing it's thing. This is quite a serious issue for my game! To give you some idea of my issue: After 1000 frames: 600 fps 56 bytes used by lua After 50000 frames: 300 fps 2533 bytes used by lua This is the function that gets called every frame:
	-- called every frame
	OnFrame = function()
		-- get the renderer
		local renderer = Renderer_GetCurrent()

		-- clear the renderer (colour, zbuffer, stencil)
		Renderer_Clear(renderer, true,true,false);
		
		-- tell the renderer we're about to render stuff
		Renderer_Begin(renderer)
		
		-- render a grid (just for debugging)
		Renderer_DebugDrawGrid(renderer, 0,0,0)
		
		-- render the world (and therefore all the nodes)
		World_Render(mainWorld)
		
		-- tell the renderer we've finished rendering
		Renderer_End(renderer)
		
		-- present causes the renderer to copy itself to the screen
		Renderer_Present(renderer)
	end,

Thanks for any suggestions!

Share this post


Link to post
Share on other sites
Advertisement
Are you recreating the OnFrame function each time you update your frame? That could be the cause of the memory increase and the only explanation I could gather from your snippet. Could you post the entire script and how you are executing it?

Share this post


Link to post
Share on other sites
Sure, here's the code:


// send a script message about this frame
ceScript->PushFunction("Messages", "OnFrame");
ceScript->CallFunction(0);




and the two functions:


void CScript::PushFunction(const char* tblName, const char* funcName)
{
// get function to be called
if (tblName)
{
lua_getglobal(luaVM, tblName);

// get function key
lua_pushstring(luaVM, funcName);

// table resides at stack index -2
lua_gettable(luaVM, -2);
}
else
{
// no table, just a global function
lua_getglobal(luaVM, funcName);
}

if (!lua_isfunction(luaVM, -1))
{
CONSOLE_ERR("Lua error : '%s' is not a function", funcName);
lua_pop(luaVM, 1); // pop error message from the stack

return;
}
}

BOOL CScript::CallFunction(int noofParams)
{
int error;

// do the call
error = lua_pcall(luaVM, noofParams, 1, 0);

if (error)
{
CONSOLE_ERR("Lua error : %s", lua_tostring(luaVM, -1));
lua_pop(luaVM, 1); // pop error message from the stack

return FALSE;
}

return TRUE;
}




I should point out that the 'OnFrame' lua function is in the table 'Messages'. I took it out of that table (so it was global) but that made no difference.

Share this post


Link to post
Share on other sites
I think the problem is with the CScript method PushFunction. Because it is not a lua_Function the stack is not getting cleaned up once you are done working. So garbage tends to stack up and the gc need more time to take care of it.

Try this and see if it helps:


void CScript::PushFunction(const char* tblName, const char* funcName)
{
// save the stack's starting state
const int top = lua_gettop(luaVM);

// get function to be called
if (tblName)
{
lua_getglobal(luaVM, tblName);

// get function key
lua_pushstring(luaVM, funcName);

// table resides at stack index -2
lua_gettable(luaVM, -2);

// remove the table that is still stacked
lua_remove(luaVM, -2);
}
else
{
// no table, just a global function
lua_getglobal(luaVM, funcName);
}

if (!lua_isfunction(luaVM, -1))
{
CONSOLE_ERR("Lua error : '%s' is not a function", funcName);

// restore the stack to its previous state.
lua_settop(luaVM, top);
}
}


Share this post


Link to post
Share on other sites
OK I'll give that a go when I get home tonight and let you know how I get on.

Cheers.

Share this post


Link to post
Share on other sites
OK i've figured it out. I wrote a simple test that looks like:


do
{
// get function key
lua_pushstring(ceScript->GetLuaVM(), "DoNothing");

// call the function with 0 parameters and 0 returns
lua_pcall(ceScript->GetLuaVM(), 0, 0, 0);

// WARNING!!! Not calling this results in the stack not being clean
lua_pop(ceScript->GetLuaVM(), 1);

dprintf("gettop = %i\n", lua_gettop(ceScript->GetLuaVM()));

dprintf("Lua mem = %i\n", ceScript->GetMemoryUse());

}while(true);



Without the lua_pop(), the stack just keeps getting larger and larger. Which makes sense really, with every push you have to call pop (although lua_pcall() pops the arguments for you if there was any).

lua_gettop() is pretty damn usefull to see what's going on.

Anyway, thanks for the help.

Jim

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement