lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Our app allows users to register a Timer function which gets called periodically. I've noticed that some patterns of Lua code cause memory to grow to the point that the OS starts killing processes as if the garbage collector isn't being run. Other seemingly similar Lua code has flat memory usage. 

The C code looks something like this ( simplified but basically the same )

static int functionIndex = -1;

static int SetHandler( lua_State* L ) {
  if( functionIndex != - 1) {
    luaL_unref(L, LUA_REGISTRYINDEX, functionIndex);
  }
  if( lua_isfunction(L,-1)) {
    lua_pushvalue(L,-1);
    functionIndex = luaL_ref(L,LUA_REGISTRYINDEX);
  }
  return 0;
}

static const struct luaL_reg TestLibMethods[] = {
  { "SetHandler", SetHandler },
  {NULL, NULL}
};

static void CallHandler(lua_State* L) {
  if(functionIndex != -1 ) {
    lua_rawgeti(L, LUA_REGISTRYINDEX, functionIndex);
    lua_pcall( L, 0, 0, 0 );
  }
}

This code will run fine with no memory growth

function A_callback()
  A()
End

function A()
  Timer.SetHandler( A_callback )
end

Timer.Start( .1 )
A()

This code has unbounded memory growth

function A()
  function A_callback()
    A()
  end
  Timer.SetHandler( A_callback )
end

Timer.Start( .1 )
A()

This code ( basically above, but manually calling the gc ) has flat memory usage

function A()
  function A_callback()
    A()
  end
  Timer.SetHandler( A_callback )
  collectgarbage("collect")
end

Timer.Start( .1 )
A()

So the only difference is that in once case the function assigned to SetHandler is contained within the function and in the other case it isn't. I could buy that somehow having the function be a child would cause an unexpected reference but then I don't understand why manually calling collectgarbage fixes anything. Any ideas what might be going on?