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

2024-04-04

我正在寻找一个描述提高 Lua 性能的各种技术的文档 http://www.lua.org/gems/sample.pdf脚本代码,我很震惊竟然需要这样的技巧。 (虽然我引用的是 Lua,但我在 Javascript 中也见过类似的 hack)。

为什么需要这种优化:

例如,代码

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

运行速度比这个慢 30%:

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

他们重新宣告sin本地运行。

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

我在 Javascript 中看到过类似的东西;所以显然必须有一个very这是解释编译器没有完成其工作的充分理由。它是什么?


我在我正在摆弄的 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没有能力被profile
  3. Lua不应该优化

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

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

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

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

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

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

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

Update: 我刚读完Lua 性能技巧 http://www.lua.org/gems/sample.pdf作者是 Lua 作者之一 Roberto Ierusalimschy,它几乎解释了您需要了解的有关 Lua、性能和优化的所有内容。 IMO 最重要的规则是:

Rule #1: 不要这样做。

Rule #2: 还别做。 (仅供专家参考)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么这个 Lua 优化 hack 会提高性能? 的相关文章

  • 缓存施瓦茨变换

    我正在学习 中级 Perl 它非常酷 我刚刚读完 施瓦茨变换 部分 在理解它之后 我开始想知道为什么变换不使用缓存 在具有多个重复值的列表中 转换会重新计算每个值的值 因此我想为什么不使用哈希来缓存结果 这是一些代码 a place to
  • 使用 ScriptEngine 从 JavaScript 调用 Java 方法

    我正在使用 ScriptEngine 运行 JavaScript 我希望 JavaScript 脚本能够调用 myFunction 其中 myFunction 是我的给定类中的一个方法 我知道可以将 importPackage 用于标准 J
  • 单个返回语句与多个返回语句? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 VB6 中计时函数/测量性能的最佳方法是什么?

    如果我只想快速测量特定函数花费的时间 我可以调用什么来获得准确的计时 鉴于VB6计时函数精度不高 是否可以调用Windows API函数 您还通过哪些其他方式衡量应用程序性能 有推荐的第三方工具吗 我通常使用 Windows 高分辨率性能计
  • Lua 中的贪婪/非贪婪模式匹配和可选后缀

    在 Lua 中 我正在尝试模式匹配和捕获 384 Critical Strike Reforged from Parry Chance as 384 Critical Strike 后缀在哪里 Reforged from s 是可选的 长版
  • 不必记住我要拉和推的分支的最佳别名是什么?

    这里非常懒 不喜欢输入太多 特别不喜欢记住我在哪个分支上拉出和推入 我经常犯这样的错误git pull来自非主分支 或者更糟糕的是 进行推送并且目标分支不正确 并且我留下了未推送或未提交的更改 我在我的 bashrc以下别名可以提供帮助 a
  • libc++ 中短字符串优化的机制是什么?

    这个答案 https stackoverflow com a 10319672 1805388给出了短字符串优化 SSO 的高级概述 但是 我想更详细地了解它在实践中是如何工作的 特别是在 libc 实现中 字符串必须有多短才能符合 SSO
  • 可以通过Data.Function.fix来表达变形吗?

    我有这个可爱的fixana这里的函数执行速度比她的姐妹快 5 倍左右ana 我有一个criterion报告支持我这一点 ana alg Fix fmap ana alg alg fixana alg fix f gt Fix fmap f
  • Linq 是如何工作的(在幕后)?

    我正在考虑为 Lua 制作类似 Linq 的东西 并且我大致了解 Linq 的工作原理 但想知道是否有一篇好文章 或者是否有人可以解释 C 如何使 Linq 成为可能 注意 我的意思是在幕后 比如它如何生成代码绑定等等 而不是最终用户语法
  • Matlab 和 Python 中的优化算法(dog-leg trust-region)

    我正在尝试使用 Matlab 和 Python 中的狗腿信赖域算法求解一组非线性方程 在Matlab中有fsolve https www mathworks com help optim ug fsolve html其中此算法是默认算法 而
  • 如何使用 echo 命令写入并附加到文件

    我正在尝试编写一个脚本 它将使用 echo 并写入 附加到文件 但我的语法中已经有了 字符串 说 echo I am Finding difficult to write this to file gt file txt echo I ca
  • 编译过程

    谁能解释一下编译是如何工作的 我似乎无法弄清楚编译是如何工作的 更具体地说 这是一个例子 我正在尝试在 MSVC 6 中编写一些代码来加载 Lua 状态 我已经 设置库的附加目录并将文件包含到正确的目录中 使用 extern C 因为 Lu
  • lua-socket:unix 域套接字?

    我使用的是 lua socket 3 0rc1 3 Ubuntu Trusty 附带的 和 lua 5 1 我正在尝试监听 unix 域套接字 我能找到的唯一示例代码是this http lua users org lists lua l
  • 如何将 Lua 粘合到 C++ 代码?

    您使用 Luabind toLua 或其他库 如果使用 是哪一个 还是根本不使用 每种方法都有哪些优点和缺点 我不太同意 自己投票 将基本类型和静态 C 函数绑定到 Lua 是微不足道的 是的 但是当你开始处理表和元表时 情况就会发生变化
  • 在 bash 中添加(收集)退出代码

    我需要依赖于脚本中的几个单独的执行 并且不想将它们全部捆绑在一个丑陋的 if 语句中 我想使用退出代码 每次执行并添加它 最后 如果这个值超过阈值 我想执行一个命令 伪代码 ALLOWEDERROR 5 run something RESU
  • 相当于 min() 的 rowMeans()

    我在 R 邮件列表上多次看到这个问题 但仍然找不到满意的答案 假设我有一个矩阵m m lt matrix rnorm 10000000 ncol 10 我可以通过以下方式获得每行的平均值 system time rowMeans m use
  • requestAnimationFrame 垃圾回收

    我正在使用 Chrome 开发工具 v27 中的时间轴分析以下代码的内存使用情况
  • 调度算法,找到设定长度的所有非重叠区间

    我需要为我的管理应用程序实现一种算法 该算法将告诉我何时可以将任务分配给哪个用户 我实现了一个蛮力解决方案 它似乎有效 但我想知道是否有更有效的方法来做到这一点 为了简单起见 我重写了算法以对数字列表进行操作 而不是数据库查询等 下面我将尝
  • 优化我的表现

    我正在开发一个使用 Zend Framework 1 11 Doctrine 2 一些 Symfony 2 组件以及其他工具和库的项目 我正在尝试使用 Xdebug 和 Webgrind 优化性能 我已经发现了一些瓶颈 例如解析 Ini 配
  • 同一索引操作上的不同估计行?

    简介和背景 我必须优化一个简单的查询 下面的示例 重写几次后 我认识到同一个索引操作的估计行数会根据查询的编写方式而有所不同 最初 该查询执行了聚集索引扫描 因为生产中的表包含二进制列 该表相当大 大约 100 GB 并且全表扫描执行起来需

随机推荐

  • Furo Sphinx 主题在 API 文档中保留过多的大写字母

    我面临着这个问题中讨论的同样的问题 Furo Sphinx 主题在 API 文档中大写过多 https stackoverflow com questions 69873561 furo sphinx theme uppercases to
  • Angular2 ngOnDestroy,发出事件

    是否可以在 ngOnDestroy 上发出自定义事件 我尝试过 但似乎不起作用 我基本上需要知道指令何时从 UI 中删除 Output rowInit new EventEmitter Output rowDestroy new Event
  • 如何统计group by返回的组数?

    select count as count from table group by foreign id order by count 这将返回每个外部 ID 的多个匹配项 然而 我正在寻找的是总结结果 所以结果是 10 results g
  • 我需要双向创建 automapper createmap 吗?

    这可能是一个愚蠢的问题 n00b 到 AutoMapper 并且时间很短 我想使用 AutoMapper 从 EF4 实体映射到 ViewModel 类 1 如果我打电话 CreateMap
  • 表单位置位于屏幕右下角

    我正在使用 c WinForm 开发 sman 通知应用程序 我想将主窗体放置在屏幕工作区域的右下角 在多个屏幕的情况下 有没有办法找到最右边的屏幕来放置应用程序 或者至少记住上次使用的屏幕并将表单放置在其右下角 我目前没有多个显示器可供检
  • Python/Matplotlib - 快速更新轴上的文本

    我在 wxpython 窗口中有一个 matplotlib 图 画布 我想在鼠标移动时更新绘图上的一些信息 我已连接到 motion notify event 来获取此信息 在下面的代码中 绘制了大量随机数据 然后在窗口的状态栏中显示光标的
  • 如何使用 Consul 中定义的默认值在 Terraform 中定义可选变量

    我有一个 Terraform 脚本 其中包含一些从 Consul 填充的变量 我想在两种不同的场景中使用这个脚本 场景 1 使用 Consul 的默认值一切正常 场景 2 我需要覆盖一些变量 我检查了 Terraform 文档 发现我无法使
  • 在 Golang 中取消引用地图索引

    我目前正在学习 Go 我制作了这个简单粗暴的库存程序只是为了修补结构和方法以了解它们是如何工作的 在驱动程序文件中 我尝试从收银台类型的项目映射中调用方法和项目类型 我的方法有指针接收器来直接使用结构而不是复制 当我运行该程序时 我收到此错
  • 如何使用javascript检查客户端系统中是否安装了特定软件?

    是否可以使用Javascript检测客户端系统是否安装了特定的Windows应用程序 我开发了一个网站 该网站必须检测仅由我们开发的应用程序 但我想让你知道 网站名称和 Windows 应用程序名称是不同的 我的意思是考虑我的网络应用程序名
  • Python:string.uppercase 与 string.ascii_uppercase

    这可能是一个愚蠢的问题 但我不明白字符串模块中 string uppercase 和 string ascii uppercase 之间有什么区别 打印两个函数的文档字符串会打印相同的内容 甚至输出print string uppercas
  • 在一次搜索中搜索 LDAP 上的用户和关联组

    LDAP 新手 我们的 LDAP 的排列方式是 人员 和 组 人们拥有姓名 uid 和邮件等用户信息 这些组具有组名称和多个成员字段 其值如 cn First Last cn people dc comic dc com 列出了该组成员的人
  • 在其声明之上调用函数

    void foo bar error bar has not been declared void bar namespace N void foo N bar error bar is not a member of N void bar
  • Visual Studio Code:.git 文件夹/文件隐藏

    我现在正在尝试 Visual Studio Code 关于 Visual Studio Code 的所有内容对我来说都非常酷 除了一件事 git 文件夹 文件隐藏在 Visual Studio Code 中 我经常通过修改 git配置文件
  • 如何在不复制粘贴的情况下以相同的方式扩展两个类?

    我写了一个楼主画的TabControl 但是我们的项目也使用了TabWorkspace其源自TabControl 此刻 我有 public class OurTabControl TabControl some code that over
  • 如何在窗口栏中获取菜单?

    我想知道如何在窗口栏中获取菜单 就像 Visual Studio 一样 如果能够在左侧显示 文件 编辑 等按钮 在右侧显示标准的 最小化 最大化 和 关闭 按钮 那就太好了 这是可能吗 我尝试过设置Window WindowStyle No
  • Android Intent Data Uri 查询参数

    我正在尝试使用如下意图启动我的应用程序 adb shell am start a android intent action VIEW d my scheme my host queryParam1 QueryParam1 queryPar
  • Xcode 8 无法导出 Ad Hoc 发行版的存档版本

    当我尝试在 Xcode 8 中导出存档应用程序以进行临时分发时 我收到一条错误消息 有没有匹配的配置文件 and 现有的配置文件缺乏应用程序标识符和钥匙串访问组权利 有什么问题吗 我怎样才能让它发挥作用 我尝试在开发人员会员中心生成临时分发
  • CoreData 和 mergeChangesFromContextDidSaveNotification

    我正在创建一个addingManagedObjectContext 作为新实体的便笺簿区域 然后在 保存 时将新实体合并到我的主 ManagedObjectContext 中 类似于 CoreDataBooks 示例中的显示方式 合并新实体
  • AWS Amplify Graphql 对 @connection 的查询

    我正在使用 AWS Amplify 前端使用 Cli 和 Angular 7 进行 Graphql AppSync 并且想知道当超过 10 个项目时如何获取所有连接的项目 假设我创建了一个这样的 schema graphql type Us
  • 为什么这个 Lua 优化 hack 会提高性能?

    我正在寻找一个描述提高 Lua 性能的各种技术的文档 http www lua org gems sample pdf脚本代码 我很震惊竟然需要这样的技巧 虽然我引用的是 Lua 但我在 Javascript 中也见过类似的 hack 为什