我本来在做一个简易的日志输出,日志字符串达到一定长度之后,就把字符串裁切只留下后面一半。
我不经意间使用了 utf8.sub()
来裁,然后我发现游戏过程中莫名其妙就卡顿几十秒,然后就恢复,也不像是我哪里有逻辑死循环。
经过反复 print()
来找卡顿的实际位置,我终于找到了原因,就是这个 log 裁切的问题。
Gmod Wiki 里说 utf8.sub() 比较吃性能,不要在逐帧运行的部分里使用。
可我没想到你这性能问题这么大啊。
下面是测试代码和测试结果:
concommand.Add(
"test1",
function()
local t1 = SysTime()
print("start")
local str1 = ""
for i = 1, 199 do
str1 = str1 .. "甲甲甲abc abc== 123456123 甲甲甲 abc 123456123甲甲"
end
local t2 = SysTime()
print(Format("拼字符串 用时 %.3f 文本长度: %d %d", t2 - t1, #str1, utf8.len(str1)))
local str2 = string.sub(str1, 9999)
local t3 = SysTime()
print(Format("string.sub 用时 %.3f 文本长度: %d", t3 - t2, #str2))
local str3 = utf8.sub(str1, 5000)
local t4 = SysTime()
print(Format("utf8.sub 用时 %.3f 文本长度: %d", t4 - t3, #str3))
end
)
-- 本地单人游戏 intel i7-12650H
-- start
-- 拼字符串 用时 0.000 文本长度: 11542 8358
-- string.sub 用时 0.000 文本长度: 1544
-- utf8.sub 用时 10.642 文本长度: 4637
8358 个字符(11542 字节)的字符串裁掉一半就要花 10 秒。
这也 tmd 太慢了吧。
string.sub()
是像切割 byte[] 一样切割字符串, utf8.sub()
是先把字符串拆成一个个 utf8 字符,然后再组。
非必要不使用,还是老老实实用 string.sub
吧,开头有两个乱码字符没什么大不了的(