Lua模塊的加載與內存釋放


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

 

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

前往下載頁面 http://luajit.org/download.html  ,然后下載最新版本

image

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

image

進入下載好的 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

function unrequire(m)
    package.loaded[m] = nil
    _G[m] = nil
end

 

實際測試的示例

內存回收

上面的20.xx是M,你沒看錯。一個約4.5M的 lua 文件,被 require 進內存后,lua 所占用的內存大小變為 20M。為什么會這么大,有待進一步從源碼中尋找答案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM