优化编码技巧 |
|
t[#t+1] = 0 比 table.insert(t, 0) 快。
x * (1/3) 与 x * 0.33333333333333333 一样快,并且通常比 x/3 在大多数 CPU 上更快(参见下面的乘法说明)。1 + 2 + x 与 (1+2) + x 相同,应该与 3 + x 或 x + (1 + 2) 一样快,但比 x + 1 + 2 快,后者与 (x + 1) + 2 相同,因为它们不一定等效于前者。请注意,计算机上的数字加法通常在发生溢出时不是结合的,编译器甚至不知道 x 是一个数字还是具有非结合 __add 元方法的其他类型。 - LuaList:2006-03/msg00363.html 。据报道,Roberto 正在认真考虑从 Lua 5.2 中删除常量折叠,因为常量折叠一直是 Lua 中错误的来源(尽管我们中的一些人真的很喜欢常量折叠 - DavidManura)。
x*0.5 比除法 x/2 快。
x*x 比 x^2 快
x*y+x*z+y*z --> x*(y+z) + y*z。Lua 不会为你做这件事,特别是因为它不能假设分配和其他的常见代数性质在数值溢出期间成立。
请注意,Roberto Ierusalimschy 在优秀的 [Lua 编程宝石] 书籍中撰写的 Lua 性能技巧文章可以在 [网上获取]。
以下信息涉及 Lua 4 的优化,并保留在此处以供历史参考。
此信息是为 Lua(v4.0 之前的版本)编写的 - Nick Trout
assert(x <= x_max, "exceeded maximum ("..x_max..")")
function fast_assert(condition, ...)
if not condition then
if getn(arg) > 0 then
assert(condition, call(format, arg))
else
assert(condition)
end
end
end
fast_assert(x <= x_max, "exceeded maximum (%d)", x_max)
这是生成的 VM 代码
assert(x <= x_max, "exceeded maximum ("..x_max..")")
GETGLOBAL 0 ; assert
GETGLOBAL 1 ; x
GETGLOBAL 2 ; x_max
JMPLE 1 ; to 6
PUSHNILJMP
PUSHINT 1
PUSHSTRING 3 ; "exceeded maximum ("
GETGLOBAL 2 ; x_max
PUSHSTRING 4 ; ")"
CONCAT 3
CALL 0 0
fast_assert(x <= x_max, "exceeded maximum (%d)", x_max)
GETGLOBAL 5 ; fast_assert
GETGLOBAL 1 ; x
GETGLOBAL 2 ; x_max
JMPLE 1 ; to 17
PUSHNILJMP
PUSHINT 1
PUSHSTRING 6 ; "exceeded maximum (%d)"
GETGLOBAL 2 ; x_max
CALL 0 0
Edit: April 23, 2012 By Sirmabus The code above will not actually work with 5.1 Also added some enhancements like pointing back to the actual assert line number, and a fall through in case the assertion msg arguments are wrong (using a "pcall()").
function fast_assert(condition, ...) if not condition then if next({...}) then local s,r = pcall(function (...) return(string.format(...)) end, ...) if s then error("assertion failed!: " .. r, 2) end end error("assertion failed!", 2) end end
table = { "harold", "victoria", "margaret", "guthrie" }
迭代此表的“正确”方法如下
for i=1, getn(table) do
-- do something with table[i]
end
但是,如果我们不关心元素顺序,上面的迭代速度很慢。第一个问题是它调用了 getn(),假设如上所述“n”字段尚未设置,则 getn() 的顺序为 O(n)。第二个问题是必须执行字节码并执行表查找以访问每个元素(即“table[i]”)。
一种解决方案是使用表迭代器
for x, element in pairs(table) do
-- do something with element
end
getn() 调用被消除,表查找也被消除。“x”是一个哑变量,因为在这种情况下通常不使用元素索引。
此解决方案有一个注意事项。如果在表上使用库函数 tinsert() 或 tremove(),它们将设置“n”字段,这将出现在我们的迭代中。
另一种方法是使用 LuaPowerPatches 中列出的列表迭代补丁。
(lhf) 表是 Lua 中的核心数据结构。你不应该担心表的性能。我们付出了很多努力来使表变得更快。例如,有一个专门的 opcode 用于 a.x。请查看 a.x 和 a[x] 之间的区别... 但是,就像你所说,这里的区别本质上是一个额外的 GETGLOBAL。
a,c = {},"x"
CREATETABLE 0
PUSHSTRING 2 ; "x"
SETGLOBAL 1 ; c
SETGLOBAL 0 ; a
b=a.x
GETGLOBAL 0 ; a
GETDOTTED 2 ; x
SETGLOBAL 3 ; b
b=a["x"]
GETGLOBAL 0 ; a
GETDOTTED 2 ; x
SETGLOBAL 3 ; b
b=a[c]
GETGLOBAL 0 ; a
GETGLOBAL 1 ; c
GETTABLE
SETGLOBAL 3 ; b
END