有更高效的方式来写这个 if (或) 语句吗?

我想确定在 Lua 中写这个语句是否更有效:

if (value == 1 or value == 2) then

例如这样的东西(我假设不起作用):

if (value == (1 or 2)) then

if value == (1;2) then
点赞
用户805875
用户805875

让我们以生成的字节码作为速度的代理。 (微基准测试 不可靠。缓存、管道、分支预测、... 可能会产生 非常 奇怪的影响,这些影响可能使本质上应该更慢的代码在实践中表现更佳,具体要看您实际使用它的上下文。字节码大小也不是很好的指标 (相同的问题适用),但至少它容易产生、确定性好并且容易解释。)

(如果您要跟随操作,请将您的测试文件传递给 luac -p -l,这将仅 p 解析 (不写入编译文件) 并 l 侧面效果地列出生成的字节码结果。如果要理解字节码,请查看 非官方字节码参考文档,该文档最初由 Kein-Hong Man 创建,Dibyendu Majumdar 友好地更新了它。但是这不是必须的。)

如果 value 是全局变量,您将获得以下内容:

1   [1] GETTABUP   0 0 -1 ; _ENV "value"
2   [1] EQ         1 0 -2 ; - 1   (跳转到下一个比较)
3   [1] JMP        0 3    ; 到 7  (true分支)
4   [1] GETTABUP   0 0 -1 ; _ENV "value"
5   [1] EQ         0 0 -3 ; - 2   (落入true分支)
6   [1] JMP        0 1    ; 到 8  (超出true分支)

将其重新翻译为“伪Lua”,大致上是这样的:

local r0 = _ENV["value"]
if r0 == 1 then  goto true_branch  end
local r0 = _ENV["value"]
if r0 ~= 2 then  goto fin  end
::true_branch::
-- stuff here
::fin::

如果 value 是函数中使用的 local 变量 (或函数参数),则会得到以下内容:

1   [1] EQ         1 0 -1 ; - 1
2   [1] JMP        0 2    ; 到 5
3   [1] EQ         0 0 -2 ; - 2
4   [1] JMP        0 1    ; 到 6

或大致上如下:

if r0 == 1 then  goto true_branch  end
if r0 ~= 2 then  goto fin  end
::true_branch::
-- stuff here
::fin::

“好多了”!

因此,如果 value 是全局变量 (或者一个 upvalue),则执行以下操作:

local value = value
if value == 1 or value == 2 then
  -- stuff
end

将会得到

1   [1] GETTABUP   0 0 -1 ; _ENV "value"
2   [1] EQ         1 0 -2 ; - 1
3   [1] JMP        0 2    ; 到 6
4   [1] EQ         0 0 -3 ; - 2
5   [1] JMP        0 1    ; 到 7

local r0 = _ENV["value"]
if r0 == 1 then  goto true_branch  end
if r0 == 2 then  goto true_branch  end
goto fin
::true_branch::
-- stuff here
::fin::

这样可节省一次查找。(虽然微基准测试将显示明显的差异,但在实践中您几乎永远不会注意到差异。如果您进行深度查找 if foo.bar.baz == 1 or foo.bar.baz == 2 then,先使用 local 是有意义的,这可能还会增加可读性。)

2017-05-15 00:45:50