4

Lua で実行する C プログラムがあります。

lua_gc() を使用して Lua のメモリ使用量を取得および制御しようとしていますが、C プロセスのメモリ使用量は依然として高いままです。Lua は 4MB のメモリしか使用しないと言っていますが、C プロセスは 150MB 以上のメモリを使用します。

また、l_alloc() 関数を使用して Lua のメモリ割り当てを追跡しようとしましたが、結果は lua_gc(LUA_GCCOUNT) と lua_gc(LUA_GCCOUNTB) を呼び出して Lua が通知したメモリ使用量と同じです。

lua_close() を呼び出して Lua 環境を閉じた後、プロセス メモリはダウンしており、正常に見えます。したがって、「失われたメモリ」はまだ C プログラムではなく Lua によって制御されていると思います。

サンプル C コードを次に示します。Lua 環境を作成し、Lua 関数を呼び出してデータをパージし、メモリ使用量を確認します。

int main()
{
    int rc;
    uint64_t gc_mem_usage;

    lua_State* Lua = luaL_newstate();
    luaL_openlibs(Lua);

    lua_gc(Lua, LUA_GCSTOP, 0);
    luaL_dofile(Lua, "test.lua");

    gc_mem_usage = ((uint64_t)lua_gc(Lua, LUA_GCCOUNT, 0) << 10) + lua_gc(Lua, LUA_GCCOUNTB, 0);
    printf("Lua mem usage: [%" PRIu64 "] Bytes\n", gc_mem_usage);

    lua_getglobal(Lua, "command_handler");
    lua_pushstring(Lua, "CC");
    rc = lua_pcall(Lua, 1, 0, 0);
    if (rc != 0 ) {
        printf("function error\n");
        return;
    }

    lua_settop(Lua, 0);

    // do full gc
    lua_gc(Lua, LUA_GCCOLLECT, 0);
    lua_gc(Lua, LUA_GCCOLLECT, 0); // I don't know why it has different result by calling full gc twice
    sleep(1);

    printf("-------------After GC ----------------------\n");
    gc_mem_usage = ((uint64_t)lua_gc(Lua, LUA_GCCOUNT, 0) << 10) + lua_gc(Lua, LUA_GCCOUNTB, 0);
    printf("Lua mem usage: [%" PRIu64 "] Bytes\n", gc_mem_usage);

    // infinite-loop
    while(1);
}

Lua サンプル コード:

local abc = {}

function command_handler(cmd)
    if (cmd == "CC") then
        abc = {}
    end
end

for i =0, 2000000 do
    abc[i] = "ABC" .. i .. "DEF"
end

出力:

Lua mem usage: [204913817] Bytes
-------------After GC ----------------------
Lua mem usage: [4219342] Bytes

出力では、Lua のメモリ使用量が GC 後に減少していることがわかりましたが、継続的にチェックすると、この C プロセスのメモリ使用量は依然として非常に高い (193.7MB) です。

 PID MINFLT MAJFLT      VSTEXT  VSIZE  RSIZE  VGROW  RGROW  MEM CMD     1/1
4622      1      0          3K 193.7M 183.9M     0K     4K  18% a.out

C プロセスのメモリ使用量を減らす解決策はありますか?

私の環境は、Ubuntu/CentOS で動作する Lua 5.1.4 です。

4

1 に答える 1

4

Lua は、提供された割り当て解除関数を呼び出すことによって、到達不能なオブジェクトを忠実に解放します (デフォルトではrealloc(block, 0))。libcおそらく断片化が激しいために、アロケーターが未使用のメモリを返すのに苦労しているようです。出力を見るとstrace(64 ビットの Debian 6 で Lua 5.1.4 とほぼ同じ数値が得られます)、C ランタイムは小さな増分で割り当てを使用することを選択しますが、割り当て解除 (より低い値でbrkの呼び出し) は続きません。brkただし、malloc_trim(M_TOP_PAD)無限ループに入る前に挿入するtopと、常駐サイズが最大 5M に大幅に減少しstrace、データ セグメントが実際に でトリミングされたことが出力に表示されbrkます。この状況では、カスタム アロケーター (プールベースなど) またはチューニングmallocパラメーターを使用すると役立つ可能性があります。

于 2013-08-08T06:57:19.813 に答える