使用Lua 局部变量来优化性能,同时比较局部变量和全局变量

在竞争激烈的游戏行业中,尤其页游,面对策划复杂和频繁的需求,使用脚本可以降低难度和成本。在使用Lua的过程中,会经常访问全局变量来作为配置文件。

在访问全局变量时,可以通过局部变量引用全局变量来优化。当然,这样的优化毫无意义。

Locals Vs Globals  from  http://lua-users.org/wiki/LocalsVsGlobals

Comparison between local and global variables:

Implementation: Locals index an array of registers on the stack, with hard-coded integer index (at least in the standard implementation -- LuaImplementations).

Globals index from a table (or userdata), typically with variable name string, stored as constant or variable, as the key.

实现:在Lua标准实现中,使用hard-code 整数索引在 registers on the stack 上索引局部变量。

在table或者userdata中,通过string常量或者string变量作为键来索引全局变量。

Performance: The above point implies that locals can be a bit faster

Still, table indexing is a fairly efficient operation in Lua (e.g. strings are interned with precomputed hash), so this point can often be ignored unless profiling indicates optimization is needed.

性能:通过实现不同,局部变量稍微比全局变量速度快。但是,在lua table中通过string来索引也是相当快。因为字符串在lua中被内化,事先计算过hash值。

所以,除非在剖析优化性能之外,性能问题可以被忽略。

Syntax: If an environment table is set, globals can be accessed in Lua code with or without explicitly naming the environment table they come from: foo, _G.foo, or getfenv().foo (or in 5.2.0work3, _ENV.foo).

This allows different styles of environment usage, such as in ModuleDefinition.

语法:如果环境table是一个集合,在环境table之外可以通过foo,_G.foo 或者getfenv().foo来获取到全局变量。

但是,局部变量只能在模块定义中获取到。

Scope: Locals are scoped within a lexical block. Globals are scoped within any number of functions assigned a given environment table at run-time.

作用域:局部变量的作用域在语法块中。在运行时,全局变量可以在任何环境table赋值的函数中获取。

Declaration: Locals must be explicitly declared, with local statement, to use them.

Globals can be accessed on-the-fly, even with variable name set at runtime

The list of locals is defined statically. The list of globals may be determined at run-time and can even change during program execution.

声明:局部变量必须通过明显的声明去定义和使用。所有局部变量的声明都是静态的。但是,全局变量可以在代码执行时,动态的访问,甚至可以在运行时设置全局变量。

所有全局变量可以在运行时来决定,设置在代码执行过程中来改变全局变量。

Standard library access: The standard library is normally exposed to a chunk via globals.

标准库的访问:所有Lua的标准库都是通过全局变量暴露给使用者。

Precedence: Locals override globals.

优先权:局部变量覆盖全局变量

Bytecode introspection: Globals are more visible in the bytecode.

Global get/sets become GETGLOBAL/SETGLOBAL opcodes with the given variable name.

It is possible to list all the globals read or written byte a compiled chunk。

Limit on number: There is a limit to the number of locals per function (MAXLOCALS, typically 200).

字节码内省:

全局变量在字节码中是可以看到的。通过制定的变量名称,获取或者设置全局变量变成了GETGLOBAL/SETGLOBAL 指令。

通过读取或者写入一个预编译好块可以罗列出所有的全局变量。

数量限制:

每一个函数中,局部变量的数量最大为200个。

Basic facts  from  Lua Performance Tips Roberto Ierusalimschy

Before running any code, Lua translates (precompiles) the source into an internal format.

This format is a sequence of instructions for a virtual machine, similar to machine code for a real CPU.

This internal format is then interpreted by C code that is essentially a while loop with a large switch inside, one case for each instruction.

Lua在运行任何代码之前,Lua预编译源代码成为内部字节码格式。

字节码格式就是虚拟机的序列化指定,类似于真正CPU的机器指令。内部字节码格式通过C语言编写的解释器通过一个基础的while loop来不断的为每一个指定执行switch。

Perhaps you have already read somewhere that, since version 5.0, Lua uses a register-based virtual machine.

The “registers” of this virtual machine do not correspond to real registers in the CPU, because this correspondence would be not portable and quite limited in the number of registers available.

Instead, Lua uses a stack (implemented as an array plus some indices) to accommodate its registers.

Each active function has an activation record, which is a stack slice where in the function stores its registers.

So, each function has its own registers2.

Each function may use up to 250 registers, because each instruction has only 8 bits to refer to a register.

  自从5.0版本,Lua使用一种register-based virtual machine 虚拟机。 “registers” 不依赖于CPU真正的指令,依赖CPU指正的registers由于registers数量限制将导致Lua的不可以移植。

相反,lua使用stack 来解决registers。每一个函数最大有250个registers,因为每一个指定仅仅有8为来执行register。

Given that large number of registers, the Lua precompiler is able to store all local variables in registers.

The result is that access to local variables is very fast in Lua.

So, it is easy to justify one of the most important rules to improve the performance of Lua programs: use locals!

依赖于大量的registers,Lua可以预编译所以的局部变量在registers中。所以,在Lua中访问局部变量非常快速。所以,在优化lua性能时,一个很重要的原则是使用局部变量:使用局部变量。

If you need to squeeze performance out of your program, there are several

places where you can use locals besides the obvious ones.

For instance, if you call a function within a long loop, you can assign the function to a local variable. 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

测试代码:

module.lua 文件:

A =1

B =1

main.lua文件:

print("=================================")

require("module")

local A =A

local t1 =os.clock ()

for i=1,100000000 do

A =2

end

local t2 =os.clock ()

print("通过局部变量来优化全局变量的访问:"..(t2-t1))

local t1 =os.clock ()

for i=1,100000000 do

B =2

end

local t2 =os.clock ()

print("直接访问全局变量:"..(t2-t1))

print("=================================")

local t1 =os.clock ()

local sin = math.sin

for i = 1, 100000000 do

local x = sin(i)

end

local t2 =os.clock ()

print("通过局部变量来优化全局变量的访问:"..(t2-t1))

local t1=os.clock ()

for i=1,100000000 do

x = math.sin(i)

end

local t2 =os.clock ()

print("直接访问全局变量:"..(t2-t1))

测试结果:

=================================

通过局部变量来优化全局变量的访问:0.825

直接访问全局变量:1.961

=================================

通过局部变量来优化全局变量的访问:7.017

直接访问全局变量:10.264

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-14 19:32:34

使用Lua 局部变量来优化性能,同时比较局部变量和全局变量的相关文章

使用Lua 局部变量来优化性能,同一时候比較局部变量和全局变量

在竞争激烈的游戏行业中,尤其页游,面对策划复杂和频繁的需求,使用脚本能够减少难度和成本.在使用Lua的过程中,会常常訪问全局变量来作为配置文件. 在訪问全局变量时,能够通过局部变量引用全局变量来优化.当然,这种优化毫无意义. Locals Vs Globals  from  http://lua-users.org/wiki/LocalsVsGlobals Comparison between local and global variables: Implementation: Locals

用好lua+unity,让性能飞起来——lua与c#交互篇

前言 在看了uwa之前发布的<Unity项目常见Lua解决方案性能比较>,决定动手写一篇关于lua+unity方案的性能优化文. 整合lua是目前最强大的unity热更新方案,毕竟这是唯一可以支持ios热更新的办法.然而作为一个重度ulua用户,我们踩过了很多的坑才将ulua上升到一个可以在项目中大规模使用的状态.事实上即使到现在lua+unity的方案仍不能轻易的说可以肆意使用,要用好,你需要知道很多. 因此,这篇文章是从一堆简单的优化建议里头,逐步挖掘出背后的原因.只有理解了原因,才能很清

【转】巧用局部变量提升javascript性能

转自:http://www.jb51.net/article/47219.htm 巧用局部变量可以有效提升javascript性能,下面有个不错的示例,大家可以参考下 javascript中一个标识符所在的位置越深,它的读写速度也越慢.因此,函数中读写局部变量总是最快的,而读写全局变量通常是最慢的.一个好的经验法则是:如果某个跨作用域的值在函数中被引用一次以上,那么就把它存储到局部变量里. 例如: 复制代码代码如下: <!-- 优化前 --> <script type="tex

IOS 通过 代码 自定义cell(Cell的高度不一致)(优化性能)

创建cell的步骤 1.新建一个继承自UITabelViewCell的类 2.重写 initWithStyle:ReuseIdentifier: 方法 添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中) 进行子控件一次性的属性设置(有些属性中需要设置一次,比如字体\固定的图片) 3.提供2个模型 数据模型:存放文字数据\图片数据 frame模型:存放数据模型\所有子控件的frame\cell的高度(可优化性能) 4.cell拥有一个frame模

ASP.NET页面优化性能提升方法记录

今天与大家分享:一种优化页面执行速度的方法.采用这个方法,可以使用页面的执行速度获得[8倍]的提升效果. 为了让您对优化的效果有个直观的了解,我准备了下面的测试结果截图: 测试环境:1. Windows Server 2003 SP22. Viaual Studio 2008,使用自带的WebDev.WebServer.EXE运行网站程序.3. (ThinkPad SL510):Core2 T6670 2.2GHz, 4G内存 二个红框中的数字反映了优化前后的执行时间.数字表明:优化前后,执行时

[经验] Win7减肥攻略(删文件不删功能、简化优化系统不简优化性能)

☆心梦无痕☆ 发表于 2014-1-24 11:15:04 https://www.itsk.com/thread-316471-1-11.html 首先 开启Administrator 用户 删除其他用户! 1.删除休眠文件 “以管理员身份运行,所有程序→附件→命令提示符”,右击选择“以管理员身份运行”,进入命令提示符后,手工输入“powercfg-h off” 这是干什么的,木星人也会知道……2.关闭系统保护计算机右键属性——高级管理设置——系统保护3.转移虚拟内存计算机右键属性——高级管理

MySQL优化 - 性能分析与查询优化

MySQL优化 - 性能分析与查询优化 优化应贯穿整个产品开发周期中,比如编写复杂SQL时查看执行计划,安装MySQL服务器时尽量合理配置(见过太多完全使用默认配置安装的情况),根据应用负载选择合理的硬件配置等. 1.性能分析 性能分析包含多方面:CPU.Memory.磁盘/网络IO.MySQL服务器本身等. 1.1 操作系统分析 常规的操作系统分析,在Linux中通常包含一些性能监控命令,如top.vmstat.iostat.strace.iptraf等. 1.内存:内存是大项,高查询消耗大量

PLSQL_硬解析和解析的区别(案例)(进行SQL优化性能调优的基础,了解解析过程)

2014-08-11 BaoXinjian 一.摘要 Oracle硬解析和软解析是我们经常遇到的问题,所以需要考虑何时产生软解析何时产生硬解析,如何判断 SQL的执行过程 当发布一条SQL或PL/SQL命令时,Oracle会自动寻找该命令是否存在于共享池中来决定对当前的语句使用硬解析或软解析. 通常情况下,SQL语句的执行过程如下: Step1. SQL代码的语法(语法的正确性)及语义检查(对象的存在性与权限). Step2. 将SQL代码的文本进行哈希得到哈希值. Step3. 如果共享池中存

第六章——根据执行计划优化性能(1)——理解哈希、合并、嵌套循环连接策略

原文:第六章--根据执行计划优化性能(1)--理解哈希.合并.嵌套循环连接策略 前言: 本系列文章包括: 1. 理解Hash.Merge.Nested Loop关联策略. 2.在执行计划中发现并解决表/索引扫描. 3. 介绍并在执行计划中发现键查找并解决它们. 对于性能优化,需要集中处理以下的问题: 1. 为你的环境创建性能基线. 2. 监控现在的性能并发现瓶颈. 3. 解决瓶颈以便得到更好的性能. 一个预估执行计划是描述查询将会如何执行的一个蓝图,而一个实际执行计划就是一个查询执行时实际发生的