lua-users home
lua-l archive

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


Hi everyone!

I am working on a code that calls a Lua function with an object argument with the C API.

When the Lua function body is empty, the program consumes a lot of memory:

function callback(object) end

However, if I add a variable declaration, the memory usage is low throughout the execution:

function callback(object)
    local _ = {}
end

I would like to know if this is expected and why.

I made a test program to measure memory consumption depending on some parameters:

usage: ./test dummy_table_bool test_iterations userdata_size

Results:

./test 0 5000000 8
lua memory usage = 186.95 MB
alive objects = 1378824

./test 1 5000000 8
lua memory usage = 0.05 MB
alive objects = 36

./test 0 5000000 1024
lua memory usage = 178.31 MB
alive objects = 173103

./test 1 5000000 1024
lua memory usage = 0.68 MB
alive objects = 240

Code:

#include <stdio.h>
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

long long aliveObjectsCount = 0;

int destructObject(lua_SdestroyeduaState) {
    --aliveObjectsCount;
    return 0;
}

void registerObjectMetatable(lua_State *luaState) {
    luaL_newmetatable(luaState, "Object");
    luaL_Reg functions[] = {{"__gc", destructObject}, {NULL, NULL}};
    luaL_setfuncs(luaState, functions, 0);
}

void pushObject(lua_State *luaState, size_t userDataSize) {
    lua_newuserdata(luaState, userDataSize);
    luaL_setmetatable(luaState, "Object");
    ++aliveObjectsCount;
}

void test(lua_State *luaState, unsigned testIterationsCount, size_t userDataSize) {
    for (unsigned i = 0; i < testIterationsCount; ++i) {
        lua_getglobal(luaState, "callback");
        pushObject(luaState, userDataSize);
        lua_call(luaState, 1, 0);
    }
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        puts("parameters: dummy_table_bool test_iterations userdata_size ");
        return EXIT_FAILURE;
    }
    const int withDummyTable = atol(argv[1]);
    const unsigned testIterationsCount = atol(argv[2]);
    const size_t userDataSize = atol(argv[3]);
    lua_State *luaState = luaL_newstate();
    luaL_openlibs(luaState);
    registerObjectMetatable(luaState);
    if (withDummyTable) {
        luaL_dostring(luaState, "function callback(object) local _ = {} end");
    } else {
        luaL_dostring(luaState, "function callback(object) end");
    }
    test(luaState, testIterationsCount, userDataSize);
    printf("lua memory usage = %.2f MB\n", lua_gc(luaState, LUA_GCCOUNT)/1024.0);
    printf("alive objects = %lld\n", aliveObjectsCount);
    lua_close(luaState);
    return EXIT_SUCCESS;
}

André Henriques