天天看點

Lua子產品的加載與記憶體釋放

今天早上聽說一件事情讓我覺得很詭異的事情:公司線上的一款遊戲,加載一份配置資源後,記憶體漲了幾十M,然後記憶體再也下不來了。因為好奇,是以要來了最大的一個配置檔案(4.5M,去除空格與換行後的大小),進行測試。最終發現,記憶體其實是可以被釋放的,不過需要注意以下的規則。

同時,為了證明luac 與 luajit 表現一緻,我同時也使用了 luajit 進行了測試。

Lua子產品的加載與記憶體釋放

在開始菜單中找到 Visual Studio的 Command Prompts

Lua子產品的加載與記憶體釋放

進入下載下傳好的 luajit 解壓目錄 LuaJIT-2.1.0-beta2/src  運作 msvcbuild.bat

重點在子產品的編寫,子產品編寫的方法導緻了釋放記憶體的不同。

當 require 準備加載一個 lua 檔案時,它會先檢測 package.loaded[modulename] 是否傳回 false,如果不是 false,它直接傳回相應存儲的值,否則查找并加載相應的檔案,找不到就報錯。

當加載的一個 lua 子產品,如果沒有 return 任何值時,package.loaded[modulename] 值為 true。

當加載一個 lua 子產品,傳回一個 table 時,package.loaded[modulename] 值為 table。

我拿到的 lua 檔案是這樣定義的,原本是一個json,将其轉為lua的,将所有資料指派給一個變量(require 之後多了一個全局變量),這樣 package.loaded[modulename] 為 true,重置這個值并不會回收記憶體,需要同時清理全局變量(将相應變量置為 nil),才可以實作記憶體的回收。

示例代碼:

local a = require(“b”) -- clear a = nil package.loaded[“b”] = nil collectgarbage() print(collectgarbage("count") / 1024)

可以針對上面的函數,封裝一個unrequire

實際測試的示例

Lua子產品的加載與記憶體釋放

上面的20.xx是M,你沒看錯。一個約4.5M的 lua 檔案,被 require 進記憶體後,lua 所占用的記憶體大小變為 20M。為什麼會這麼大,有待進一步從源碼中尋找答案。