Lua优化".."(字符串连接)操作符吗?

我必须在一个循环中执行以下代码数千次(这是一个打印目录树的递归):

local filename = dir .. "/" .. base

现在,我想知道 Lua 是否一次性连接 3 个字符串(dir,"/",base)(即,通过分配足够长的字符串来容纳它们的长度),还是通过在内部进行两个步骤的低效方式来执行:

local filename = (dir .. "/")              -- step1
                               .. base     -- step2

后者在内存方面是低效的,因为分配了两个字符串而不是一个。

我不太关心 CPU 循环次数:我主要关心内存消耗。

最后,让我概括一下问题:

当执行以下代码时,Lua 是否只分配一个字符串或 4 个字符串?

local result = str1 .. str2 .. str3 .. str4 .. str5

顺便说一句,我知道可以这样做:

local filename = string.format("%s/%s", dir, base)

但是我还没有对它进行基准测试(内存和 CPU 敏感)。

(顺便说一句,我知道关于 table:concat()。这增加了创建表的开销,因此我猜它在所有用例中都不利。)

一个奖励问题:

如果 Lua 不优化 ".." 运算符,那么定义一个 C 函数来连接字符串是否是一个好主意,例如 utils.concat(dir, "/", base, ".", extension)

点赞
用户1009479
用户1009479

在你的示例中, .. 运算符是否进行了优化对于性能来说几乎不是问题,您不必担心内存或 CPU。而 table.concat 可以用于连接多个字符串。 (参见《Lua 编程》了解使用 table.concat

回到你的问题,在这段代码中

local result = str1 .. str2 .. str3 .. str4 .. str5

Lua 只分配了一个新字符串,可以查看 Lua 相关源代码中的 luaV_concat 循环:

do {  /* concat all strings */
    size_t l = tsvalue(top-i)->len;
    memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
    tl += l;
} while (--i > 0);
setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
total -= n-1;  /* got 'n' strings to create 1 new */
L->top -= n-1;  /* popped 'n' strings and pushed one */

您可以看到 Lua 在此循环中连接 n 个字符串,但最终只将一个字符串推回堆栈,即结果字符串。

2013-10-02 14:46:52
用户7185318
用户7185318

顺便提一下,我知道table:concat()。这会增加一些额外的开销以创建表,所以我猜它在所有的使用情况下都不会有益处。

在这种特定的使用情况(以及类似的情况),如果您担心要创建大量垃圾表,您可以考虑重用一个表:

local path = {}
...
-- 在另一个循环或函数中:
path[1], path [2] = dir,base
local filename = table.concatpath,“/”)
path [1], path [2] = nil
...

甚至可以将其推广到“concat”实用程序:

local rope = {}
function string_concat(...)
    for i = 1,select(“#”,...)do rope [i] = select(i,...)end--准备缆绳
    local res = table.concat(rope)
    for i = 1,select(“#”,...)do rope [i] = nil end -- 清除绳子
    return res
end
2022-09-22 14:42:51