将一个表格设置为空还是将表格的所有元素设置为nil更好?
2013-4-26 15:58:13
收藏:0
阅读:144
评论:3
最近我参与一次代码审查时,出现了一个关于一段 lua 代码的问题。这段代码会清空缓存并用一些数据重新初始化:
for filename,_ in pairs(fileTable) do
fileTable[filename] = nil
end
-- 在这里重新初始化
上面的循环代码是否替换为以下代码呢?
fileTable = { }
-- 在这里重新初始化
点赞
用户107090
除非你有证据证明相反,否则最好相信 Lua 的垃圾回收:当需要时只需创建一个新的空表。
2013-04-26 15:53:40
用户2198692
这是由于表的调整和重新哈希开销。当创建一个表时,它是空的。当你插入一个元素时,会发生重新哈希,表的大小增加到1。当再插入另一个元素时,也会发生同样的情况。规则是,只要没有足够的空间(在数组或散列表部分中),来容纳另一个元素,表就会增长。新的大小是最小的2的幂,可以容纳所需数量的元素。例如,如果表中包含0、1、2、4、8等元素,则插入一个元素时会发生重新哈希。
现在你描述的技术可以节省这些重新哈希,因为Lua不会缩小表。因此,当你频繁地填充/清空表时,最好(从性能的角度来看)使用你的示例,而不是创建一个空表。
更新:
我进行了一个小测试:
local function rehash1(el, loops)
local table = {}
for i = 1, loops do
for j = 1, el do
table[j] = j
end
for k in ipairs(table) do table[k] = nil end
end
end
local function rehash2(el, loops)
for i = 1, loops do
local table = {}
for j = 1, el do
table[j] = j
end
end
end
local function test(elements, loops)
local time = os.time();
rehash1(elements, loops);
local time1 = os.time();
rehash2(elements, loops);
local time2 = os.time();
print("Time nils: ", tostring(time1 - time), "\n");
print("Time empty: ", tostring(time2 - time1), "\n");
end
结果很有趣。在Lua 5.1上运行test(4, 10000000),空表和nil的时间分别为10秒和7秒。超过32个元素的表,空表版本更快(表越大,差距越大)。test(128,400000),空表的时间是5秒,nil的时间是9秒。
现在在LuaJIT上,分配和垃圾回收操作相对较慢,运行test(1024, 1000000),空表的时间是7秒,nil的时间是3秒。
附注:请注意纯Lua和LuaJIT之间的性能差异。对于1024个元素的表,纯Lua需要大约20秒来执行100,000次测试迭代,而LuaJIT在10秒内执行了1,000,000次迭代!
2013-04-26 16:25:56
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
在 Lua 中分配一个新表是一项昂贵的操作(对于几乎任何动态语言中的任何对象分配也是如此)。此外,不断将新创建的数据交给垃圾收集器 GC 会给性能和内存带来额外的负担,因为每个创建的表将一直在内存中,直到 GC 真正来索取它。
你的示例技巧是用表格中所有元素的时间来换取这些劣势。这将始终是一种节省内存的方式,而且根据元素数量的不同,可能也是一种提高性能的方式。