|[ LiB ]|
Like most high-level languages, Lua manages memory automatically, so that you don't have to worry about allocating memory for new objects and freeing it when the objects are no longer needed. Lua manages memory automatically by running a garbage collector from time to time to collect any objects that are no longer accessible to Lua. The garbage collector picks up all of Lua's objects, including threads, tables, and so on.
Although this is not an issue when running the Lua interpreter, when calling Lua from a host, Lua's stack-in memory must be managed. Each function call in Lua needs one stack position for each argument, local variable, and temp variable, plus one position for bookkeeping. The stack should also have some 20 extra positions available. For small implementations of Lua (without, say, recursive functions), the Lua user manual suggests a stack size of 100. The default is 1,024.
lua_Stat *lua_open (int stacksize);
To release Lua, you close its state with the stack:
void lua_close (lua-Stat *L);
This destroys all objects in a given Lua environment by calling the corresponding garbage-collection tag methods and frees all of the dynamic memory used by that state. You do not normally need to call this function because all resources are released when your program ends. However, long-running programs like Web servers or game-server hosts may need to release states as soon as they are no longer needed so that the states don't grow too large.
When you use the Lua C API, you are responsible for controlling stack overflow. Whenever Lua calls C, it ensures that at least LUA_MINSTACK positions are available, so that you only have to worry about stack space when your code has loops pushing elements onto the stack. The API offers a number of functions for basic stack manipulation, including
void lua_settop. Sets the stack top.
void lua_pushvalue. Pushes onto the stack.
void lua_remove. Removes element at given position.
void lua_insert. Moves top element into given position, shifting elements on top of that position to open space.
void lua_replace. Replaces a given element.
You can also query the stack with a number of functions that check the type of the given object and return strings. These functions include the following:
lua_type lua_isnil lua_isboolean lua_isnumber lua_isstring lua_istable lua_isfunction lua_iscfunction lua_isuserdata lua_islightuserdata
lua_equal and lua_rawequal are functions for comparing two values on the stack.
To push C values onto the stack, there are a number of functions that receive C values, convert them to corresponding Lua values, and push the result onto the stack. These include:
lua_pushboolean lua_pushnumber lua_pushlstring lua_pushstring lua_pushnil lua_pushcfunction lua_pushlightuserdata
When chunks are called, functions like lua-dowhile push onto the stack any values eventually returned by the chunks. A chunk can return any number of values, and Lua checks to make sure the values fits within the stack space. But after the call, the responsibility for fitting within the stack falls back to the programmer. This means that if you need to push other elements after calling any of these functions, you should check the stack space and remove returned elements from the stack if you do not need them.
Lua uses two variables to control its garbage collection cycles. The first keeps track of how many bytes of dynamic memory Lua is using. The second variable is a threshold that, when hit, tells Lua to run the collector. These are accessible and changeable via the C API and through the gcinfo and collectgarbage functions.
Lua first counts the amount of memory it is using. If the count reaches the threshold, it runs the garbage collector. After the collection, the count is updated and the threshold is reset to twice the count value. The current count value can be retrieved with
lua_getccount (lu_State *L);
The current threshold can be retrieved with
lua getcthrechold (lua_State *L);
Each returns their values in KB. The threshold can be changed with
lua_setgcthreshold (lua_State *L, int newthreshold);
A garbage collection cycle can be forced with
long lua_collectgarbage(lua_State *L long limit);
This also returns the number of objects collected.
Garbage collector metamethods for userdata can be also set using the C API. These metemethods are called finalizers . The finalizers allow you to coordinate Lua's garbage collection with external resource management if necessary.
Lua supports coroutines as independent threads of execution. This isn't, however, a true independent multi-threaded systemit is a semi-collaborative multithreading system. That means a coroutine only suspends its execution by explicitly calling a yield routine. Lua also offers some support for multiple threads of execution via its C API, so if you have C libraries that offer kicking, then multi-threading Lua can cooperate with them.
Although garbage collection can be monitored and controlled, the main cause of low system performance is a large number of objects generated. If you are managing many objects, then the GC is an option, but it may not be always necessary.
Local variables in Lua are much quicker than global variables. This is because the locals are accessed by index. If possible, make any global variables local. Additionally, local variables are kept on the stack and so will not affect the garbage collector (their values do not need to be collected by the garbage collector, as they are created on the stack).
for loops in Lua have been optimized, and also have specialized virtual machine instructions. This means that they can be faster than while - and repeat -type loops and should be used if speed is your goal.
The built-in debugger features ( mainly hooks) can be used to profile Lua code and look for bottlenecks in execution time. There is also a Lua Profiler available on the lua-users.org site Wiki page, at http://lua-users.org/wiki/LuaProfiler.
When reading in files, Lua buffers the files in chunks, which is faster than reading files line by line.
|[ LiB ]|