将表设置为空或将表的所有元素设置为n是否更好?

时间:2013-04-26 15:02:21

标签: optimization lua

我最近在代码审查期间提出了一个关于一段lua代码的问题。有问题的代码是刷新缓存并使用一些数据重新初始化它:

for filename,_ in pairs(fileTable) do
    fileTable[filename] = nil
end

-- reinitialize here

是否有任何理由不应将上述循环替换为此?

fileTable = { }

-- reinitialize here

3 个答案:

答案 0 :(得分:4)

除非你有其他证据,否则你最好相信Lua的垃圾收集:只需在需要时创建一个新的空表。

答案 1 :(得分:2)

这是由于表调整大小/重新开发的开销。创建表时,它是空的。插入元素时,会发生重新散列并且表大小增加到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)为nils提供7秒,为空用提供10秒。对于大于32个元素的表,空版本更快(表越大,差异越大)。 test(128, 400000)为nils提供了9秒钟,为空箱提供了5秒钟。

现在在LuaJIT上,alloc和gc操作相对较慢,运行test(1024, 1000000)为nils提供3秒,为空用提供7秒。

P.S。注意普通Lua和LuaJIT之间的纯粹性能差异。对于1024个元素表,普通Lua在大约20秒内完成了100,000次测试迭代,LuaJIT在10秒内完成了1,000,000次迭代!

答案 2 :(得分:0)

在Lua中分配新表是一项代价高昂的操作(对于几乎任何动态语言中的任何对象分配都是如此)。此外,不断“丢失”新创建的GC将对性能和内存造成额外的压力,因为每个创建的表仍将在内存中,直到GC实际声称它。

示例中的技术将显示删除表中所有元素所需时间的缺点进行交换。这将始终是一个内存保存,并且根据元素的数量,通常也可以是性能改进。