optimization - 为什么这个 Lua 优化 hack 会提高性能?

标签 optimization scripting lua premature-optimization

我正在查看 document that describes various techniques to improve performance of Lua脚本代码,我很震惊竟然需要这样的技巧。 (虽然我引用的是 Lua,但我在 Javascript 中也见过类似的 hack)。

为什么需要这种优化:

For instance, the code

for i = 1, 1000000 do 
   local x = math.sin(i) 
end

runs 30% slower than this one:

local sin = math.sin 
for i = 1, 1000000 do
    local x = sin(i) 
end

他们正在本地重新声明 sin 函数。

为什么这会有帮助?无论如何,这是编译器的工作。为什么程序员必须做编译器的工作?

我在 Javascript 中见过类似的东西;显然,解释编译器没有完成其工作肯定有一个非常充分的理由。它是什么?

<小时/>

我在我正在摆弄的Lua环境中反复看到它;人们将变量重新声明为本地变量:

local strfind = strfind
local strlen = strlen
local gsub = gsub
local pairs = pairs
local ipairs = ipairs
local type = type
local tinsert = tinsert
local tremove = tremove
local unpack = unpack
local max = max
local min = min
local floor = floor
local ceil = ceil
local loadstring = loadstring
local tostring = tostring
local setmetatable = setmetatable
local getmetatable = getmetatable
local format = format
local sin = math.sin

这是怎么回事,人们必须做编译器的工作?编译器是否对如何查找format感到困惑?为什么这是程序员必须处理的问题?为什么 1993 年这个问题没有得到解决呢?

<小时/>

我似乎也遇到了一个逻辑悖论:

  1. 不进行分析就不应进行优化
  2. Lua 无法进行分析
  3. Lua 不应该被优化

最佳答案

Why would this be helpful? It's the job of the compiler to do that anyway. Why is the programmer having to do the compiler's job?

Lua是一种动态语言。编译器可以用静态语言进行很多推理,例如将常量表达式从循环中取出。在动态语言中,情况有点不同。

Lua 的主要(也是唯一)数据结构是表。 math也只是一个表,尽管它在这里用作命名空间。没有人可以阻止您修改math.sin在循环中的某个地方运行函数(甚至认为这是一件不明智的事情),并且编译器在编译代码时无法知道这一点。因此,编译器完全按照您指示它执行的操作:在循环的每次迭代中,查找 sin math 中的函数表并调用它。

现在,如果您知道您不会修改 math.sin (即您将调用相同的函数),您可以将其保存在循环外的局部变量中。由于没有表查找,因此生成的代码速度更快。

LuaJIT 的情况有点不同 - 它使用跟踪和一些高级魔法来查看代码在运行时正在做什么,因此它实际上可以通过将表达式移动到循环之外来优化循环。循环和其他优化,除了实际将其编译为机器代码之外,使其速度疯狂。

关于“将变量重新声明为本地变量” - 很多时候在定义模块时,您希望使用原始函数。当访问pairs时, max或任何使用全局变量的东西,没有人可以向您保证每次调用都是相同的函数。例如stdlib重新定义了很多全局函数。

通过创建与全局同名的局部变量,您实质上将函数存储到局部变量中,并且因为局部变量(它们是词法作用域的,这意味着它们在当前作用域和任何嵌套作用域中都是可见的)优先于全局变量,确保始终调用相同的函数。如果稍后有人修改全局,也不会影响您的模块。更不用说它也更快,因为全局变量是在全局表( _G )中查找的。

更新:我刚刚读过 Lua Performance Tips作者是 Lua 作者之一 Roberto Ierusalimschy,它几乎解释了您需要了解的有关 Lua、性能和优化的所有内容。 IMO 最重要的规则是:

Rule #1: Don’t do it.

Rule #2: Don’t do it yet. (for experts only)

关于optimization - 为什么这个 Lua 优化 hack 会提高性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4643814/

相关文章:

regex - 使用 Perl 内嵌编辑,如何在第 N 次出现字符串后插入一行?

c++ - 如何创建一个带有可变数量参数的模板函数,将参数传递给对象的正确构造函数?

lua - 如何让Lua垃圾收集器更频繁地运行?

haskell - 在库构建期间是否有 GHC 优化工作?

python - 优化二维数组

grails - 如何从我的 Grails 应用程序执行 Groovy 脚本?

linux - sed 适用于硬编码文件名,但不适用于包含所述文件名的变量

Lua 中的 Python eval()

mysql - 创建索引优化慢查询

c# - 快速校验和散列?