为什么这个 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 会提高性能? 的相关文章

  • 我可以让 C++ 编译器在编译时实例化对象吗?

    我正在编写一些代码 其中包含大量相当简单的对象 我希望它们在编译时创建 我认为编译器能够做到这一点 但我无法弄清楚如何做到 In C我可以执行以下操作 include
  • 在lua中组合两个函数

    我刚开始学习lua 所以我的要求可能是不可能的 现在 我有一个接受函数的方法 function adjust focused window fn local win window focusedwindow local winframe w
  • Lua中如何在另一个表的表成员中搜索

    我正在编写一个 lua 程序 它有一个表 该表是另一个表的成员 当我向该成员表添加新日期时 一切正常 但是 当我想在该表中搜索时 无论我给出什么键 我总是会将最后一行添加到表中 如何在该成员表中正确搜索 Stream name functi
  • lua中的权限问题

    是否需要在 corona build settings 中设置一些特定权限才能将高分永久保存在文件中 每次运行代码时都会出现 权限被拒绝 的错误 如何纠正这个错误 这是我尝试过的代码 function read score local f1
  • gcc总是做这种优化吗? (公共子表达式消除)

    作为示例 假设表达式sys gt pot atoms item gt P kind mass在循环内求值 循环只改变item 因此表达式可以简化为atoms item gt P kind mass通过将变量定义为atoms sys gt p
  • 在 Ruby 中构建字符串时,为什么铲运算符 (<<) 优于加等于 (+=)?

    我正在通过 Ruby Koans 进行工作 The test the shovel operator modifies the original string公案中about strings rb包括以下评论 Ruby 程序员倾向于使用铲子
  • 如何以编程方式指定 MATLAB 编辑器键绑定

    我想将键盘键绑定设置为Windows 默认设置我想在启动时使用startup m因为我希望在大量系统上设置此设置 首选项对话框中的等效设置是 MATLAB gt Keyboard gt Shortcuts gt Active Setting
  • 在Lua中获取前一天的日期

    谁能告诉我如何使用 Lua 获取 YYYY MM DD 格式的前一天日期 即 一个片段 它将返回运行当天的前一天的日期 Try print os date Y m d os time 24 60 60 严格来说 这只能保证在 POSIX 系
  • 用于预乘 ARGB 的 SSE alpha 混合

    我正在尝试编写一个支持 SSE 的 alpha 合成器 这就是我想出的 首先 混合两个 4 像素向量的代码 alpha blend two 128 bit 16 byte SSE vectors containing 4 pre multi
  • 如何分析Android应用程序的电池使用情况并对其进行优化?

    我想分析我的应用程序的电池使用情况 我的意思是应用程序的各个部分 例如 广播接收器 监听器 服务等 使用多少电池 我需要一个详细的列表 从列表中 我想优化电池的使用 方法与使用内存分析器类似 http android developers
  • 如何使用 Windows 命令行环境查找和替换文件中的文本?

    我正在使用 Windows 命令行环境编写批处理文件脚本 并希望用另一个文件 例如 BAR 更改文件中某些文本 例如 FOO 的每次出现 最简单的方法是什么 有内置函数吗 这里的很多答案都帮助我指明了正确的方向 但是没有一个适合我 所以我发
  • 为什么在强度降低乘法和循环进位加法之后,这段代码的执行速度会变慢?

    我正在读书阿格纳 雾 https en wikipedia org wiki Agner Fog s 优化手册 https en wikipedia org wiki Agner Fog Optimization 我遇到了这个例子 doub
  • 为什么 hibernate 在 SAVE 之前执行 SELECT?

    为什么 hibernate 在保存对象之前要进行选择 我在互联网上找不到有用的信息 这是每次保存之前的正常行为吗 我发现这个话题 选择 hibernateTemplate save 的查询运行 https stackoverflow com
  • 初始化 HashMap 的最佳方法

    我通常会这样做 HashMap
  • 编写多个mysql脚本

    是否可以在复合脚本中包含其他 mysql 脚本 理想情况下 我不想为包含的脚本创建存储过程 对于较大的项目 我想分层维护几个较小的脚本 然后根据需要组合它们 但现在 我很乐意学习如何包含其他脚本 source是一个内置命令 您可以在 MyS
  • 规范“毒”方式真的值得吗? (3NF)

    我正处于数据库设计的早期阶段 所以还没有最终的结果 并且我正在为具有可选标签的线程使用 TOXI 3表设计 但我忍不住觉得加入是并不是真的必要 也许我只需要依赖我的简单标签列posts我可以在其中存储类似 varchar 的表
  • 如何使用AWK脚本检查表的所有列数据类型? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在这里 我正在检查表中第一列的数据类型 但我想知道AWK中表的所有列数据类型 我尝试过 但只能获得一列数据类型 例如 Column 1
  • std::类似向量的类经过优化以容纳少量项目[重复]

    这个问题在这里已经有答案了 在程序的一个时间关键部分中 有一个类成员如下所示 std vector m vLinks 在分析过程中 我注意到该向量大约 99 98 的执行仅包含 0 或 1 个项目 然而 在极少数情况下 它可能会容纳更多 根
  • 确定向量中是否存在元素的最有效方法

    我有几种算法取决于确定元素是否存在于向量中的效率 在我看来 这 in 这相当于is element 应该是最有效的 因为它只返回一个布尔值 在测试了几种方法之后 令我惊讶的是 这些方法是迄今为止效率最低的 以下是我的分析 随着向量大小的增加
  • 如何将 bash 脚本的整个输出保存到文件

    我正在尝试将 bash 脚本的整个输出保存到文件中 我目前在代码开头有一个参数 ip 地址 如下所示 bin bash USAGE Usage 0

随机推荐

  • 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 为什