引言
如果生成了大量对象,系统的垃圾回收可能会导致性能问题。本页讨论相关问题及避免问题的方法。
最小化对象创建
问题: 基本上我想最小化临时内存分配量,从而减少 GC 的调用频率(以及每次 GC 的影响?)。有人能提供一些这方面的提示吗?例如,如果我在函数 A 中声明了局部变量,那么每次调用 A 时都会分配局部变量内存吗?
(ET) 不会。局部变量保存在堆栈上,不会影响 GC。这些结构将创建一个新的垃圾回收对象
-
a..b(仅示例;任何生成字符串的结构,即 strsub() [*1] 或 lua_pushstring()。)
- 每个新字符串都会创建一个新对象。Lua 具有唯一的字符串,这意味着 Lua 中每个可能的字符串只存在一次。如果出现一个新字符串,Lua 首先会检查它是否已存在于字符串池中。如果存在,则使用对该旧字符串的引用。如果不存在,则创建一个新的字符串对象并将其放入字符串池。GC 会检查字符串池中未使用的字符串并释放它们。因此,创建大量唯一字符串会严重影响 GC。也就是说,这对 GC 很糟糕。
for i=1,100 do x="foo"..tostring(i) end -- 100 new strings
- 注意: 代码段会持有字符串常量的引用(如上面的“foo”)。因此,只要函数存在,该字符串就会存在于字符串池中;它不必在每次执行函数时都创建。
- 每次执行表构造函数时都会创建一个新表。尽量重用表。您甚至可以创建和使用 newtable/freetable 函数来管理一个未使用的表池。这样您就可以获得旧式的表内存管理,但也会遇到旧式的问题;-)
- 执行函数语句会创建一个闭包(注意:不是调用函数,而是执行函数语句!)。通常对 GC 没有大的影响,但如果您在循环中有函数语句,可能会创建大量垃圾。也就是说:
for i=1,100 do foo(function() end) end -- bad for GC
- 创建了 100 个函数闭包。
- 可变参数函数每次调用函数时都会为省略号(存储在 '
arg' 中)创建一个表。(注意:Lua 5.2 或使用 LuaJIT 后不再如此。)
- 在 Lua 4.0(和 3.x)中,userdata 对象处理方式与字符串类似。如果指针值和标签相等,则它们相等。Lua5 呢?
- 嗯,这些会加载/编译新代码,并创建字符串和(GCed)代码段。
释放局部变量
问题(接上文): 那么任何局部字符串或表在退出函数时都会被释放吗?
变量是存储对象的容器(事实上,除了数字之外,它只保存对象的指针)。存储的对象是数字、表还是其他任何东西,都与变量无关。局部变量本身也不是垃圾回收的对象。因此,您可以在不创建中间对象的情况下使用它们。我想,这才是原始发帖人想表达的意思。
- “因此,您可以在不创建中间对象的情况下使用它们。”这需要澄清吗?变量本身不创建 GC 对象,但它的值可以。您可以使用引用其他现有对象的局部变量,而无需创建需要收集的对象。但是,您不能创建新的局部对象而不创建需要稍后收集的对象。
关于存储在局部变量中的对象:一旦局部变量不再活跃,GC 就可能收集存储在那里的对象。对象的实际释放与函数范围或变量生存期无关。GC 在特定时间运行,并释放所有不再可访问的 L 对象
[*1] strsub 存在于 Lua 4 中,而不是 Lua 5。
RecentChanges · preferences
编辑 · 历史
最后编辑于 2014 年 4 月 18 日下午 1:12 GMT (差异)