Lua 通過特定算法的垃圾回收機制實現(xiàn)自動內(nèi)存管理。由于自動內(nèi)存管理機制的存在,作為程序開發(fā)人員:
Lua 的垃圾回收器會不斷運行去收集不再被 Lua 程序訪問的對象。
所有的對象,包括表、userdata、函數(shù)、線程、字符串等都由自動內(nèi)存管理機制管理它們空間的分配和釋放。Lua 實現(xiàn)了一個增量式標(biāo)記清除垃圾收集器。它用兩個數(shù)值控制垃圾回收周期,垃圾收集器暫停時間(garbage-collector pause) 和垃圾收集器步長倍增器(garbage-collector step multiplier)。其數(shù)值是以百分制計數(shù)的,即數(shù)值 100 內(nèi)部表示 1。
該數(shù)值被用于控制垃圾收集器被 Lua 自動內(nèi)存管理再次運行之前需要的等待時長。當(dāng)其小于 100 時意味著收集器在新周期開始前不再等待。其值越大垃圾回收器被運行的頻率越低,越不主動。當(dāng)其值 200 時,收集器在總使用內(nèi)存數(shù)量達到上次垃圾收集時的兩倍時再開啟新的收集周期。因此,根據(jù)程序不同的特征,可以通過修改該值使得程序達到最佳的性能。
步長倍增器用于控制了垃圾收集器相對內(nèi)存分配的速度。數(shù)值越大收集器工作越主動,但同時也增加了垃圾收集每次迭代步長的大小。值小于 100 可能會導(dǎo)致垃圾器一個周期永遠(yuǎn)不能結(jié)束,建議不要這么設(shè)置。默認(rèn)值為 200,表示垃圾收集器運行的速率是內(nèi)存分配的兩倍。
作為開發(fā)人員,我們可能需要控制 Lua 的自動內(nèi)存管理機制,可以使用下面的這些方法:
下面的示例代碼中使用了垃圾收集器相關(guān)函數(shù),如下所示:
mytable = {"apple", "orange", "banana"}
print(collectgarbage("count"))
mytable = nil
print(collectgarbage("count"))
print(collectgarbage("collect"))
print(collectgarbage("count"))
運行上面的程序,我們可以得到如下的輸出結(jié)果。請注意,輸出結(jié)果與操作系統(tǒng)類型與 Lua 自動內(nèi)存管理都有關(guān),所以可能實際運行的結(jié)果與下面不相同。
20.9560546875
20.9853515625
0
19.4111328125
從上面的程序,我們可以看出,一旦垃圾回收運行后,使用的內(nèi)存量立即就減少了。但是,我們并不需要主動去調(diào)用它。因為,即使我們不調(diào)用此函數(shù),Lua 也會按配置的周期自動的調(diào)用垃圾回收器。
顯然,如果需要,我們可以用上面的這些函數(shù)調(diào)整垃圾回收器的行為。這些函數(shù)幫且程序開發(fā)人員處理更加復(fù)雜的場景。根據(jù)開發(fā)的不同程序的內(nèi)存需求,我們可以使用到這些方法來提高程序的性能。雖然大部分情況下,我們都不會用到這些函數(shù),但是了解這些方法可以幫助我們調(diào)試程序,以免應(yīng)用上線后帶來的損失。
譯注:更多垃圾回收器的內(nèi)容請參考官網(wǎng)或者此博客。