Lua的local变量探究

标签: Lua
13人阅读 评论(0) 收藏 举报
分类:

  欢迎参与讨论,转载请注明出处。
   本文转载自:https://musoucrow.github.io/2018/04/17/lua_local/

前言

  先前看到用好Lua+Unity,让性能飞起来—LuaJIT性能坑详解一文中提到:

3.2 寄存器分配失败->减少local变量、避免过深的调用层次
很不幸的一点是,arm中可用的寄存器比x86少。LuaJIT为了速度,会尽可能用寄存器存储local变量,但是如果local变量太多,寄存器不够用,目前JIT的做法是:放弃治疗(有兴趣可以看看源码中asm_head_side函数的注释)。因此,我们能做的,只有按照官方优化指引说的,避免过多的local变量,或者通过do end来限制local变量的生命周期。

  对此自然是可以理解的,哪怕是一般语言,local变量过多也会有堆栈溢出的问题。不过我对此一直有个隐忧:Lua是拥有模块级local变量的,不知是否也受此规则影响?尽管有此隐忧,却一直没有去做相关的探究。恰逢今日遇到相关话题,便来个刨根问底吧。

200限制

  首先的发现是:一段过程下最多拥有200个local变量,且do end不算。类似这样:

local Class = {}

local test1 = 1
local test2 = 2
... --to 199

return Class

  如果超过199,则会报出main function has more than 200 local variables的错误。当然这里说的是一段过程,所以函数是另算的,同样一个函数的过程最多也不能超过200个local变量(调用函数则算转入下一个过程了)。
  这个限制是Lua与LuaJIT共有的,显然是想限制local数量的泛滥。

函数嵌套调用

  接下来便是试试函数嵌套调用了:

function Class.Do(v)
    if (v > n) then --n is a custom value
        return
    end

    local test1 = 1
    ... -- to 199

    Class.Do(v + 1)
end

  注意参数v也算是local变量的一员,所以test变量最多只能延伸到199个。以此进行递归调用的话,根据实验结果来看:

版本 嵌套上限 local变量上限
LuaJIT 325 65000
Lua5.3 4975 995000

  测试的环境为macOS x86-64,LuaJIT方面无论JIT开启与否结果皆一致。根据前文所言来看,到了ARM环境这个数量将会进一步下降。虽然从对比来看差距有点大,但实际上在函数调用方面也算够用了。

模块级local变量

  接下来便是我最关心的一点了:以上local变量上限是否会影响到模块级local变量?所谓模块级local变量即作用域为整个文件:

--test.lua
local Class = {}
local function Func()
end
...

return Class

  这种模块级local变量在Lua开发的应用还是很广泛的,它能有效的做到信息分隔的效果。但若是这些变量也受之前的上限规则影响,咁就扑街了!

  首先是测试加载多个满载local变量的模块:

for n=1, 5000 do
    require("test" .. n)
end

  天可怜见,无论读取多少个文件,都不会存在上限问题。可见对于模块级local变量的处理是不一样的。到了这里基本上可以放心了,不过为防万一,我还做了模块的嵌套引用实验:

---test1.lua

local Class = {}
print("1")
local Next = require("test2")
local test1 = 1
local test2 = 2
... --to max
return Class

  以这种形式生成了5000个文件,以此进行嵌套引用,结果也是成功通过了。由此可见,对于模块级local变量是可以放心地去使用了。

后记

  尽管模块级local变量是可以随便用了,但是也要考虑到热更新方面的问题:若是选择使用模块级local变量去存储模块的数据,那么在热更新方面的处理将会变得十分麻烦。从这点考虑的话,模块级local变量最好只是用于引用别的模块为妙。

查看评论

lua local 变量和表

local是我们在lua编程里面经常写的,经常写的方式为local foo = foo。lua对local的处理有加速访问的效果,并且将变量定义为局部变量也是一种好的编程习惯。 lu...
  • bosswanghai
  • bosswanghai
  • 2016-12-24 15:49:55
  • 2836

Lua变量生命周期

Lua变量的定义是很自由的,不需要像C语言那样必须指明类型,变量可以是任何“值”,比较特殊的一点是,可以把任何function赋值给变量,如: [plain] view plai...
  • sssssNian
  • sssssNian
  • 2014-10-22 10:41:57
  • 827

lua中尽量使用local

结论: lua 5.1.5 windows环境下 使用local变量能够稍微提高效率 但是如果有了间接引用,比如 上面代码里面 local g = {} 定义成 local a = {}, ...
  • magicpang
  • magicpang
  • 2016-04-26 10:58:05
  • 5850

redis lua local 作用域

lua 不加前缀定义的为全局变量, 例如 :  i = 1   -- 这样定义的为全局变量. 定义本地变量使用local前缀, 例如 :  local i = 1 -- 定义一个本地...
  • u013399759
  • u013399759
  • 2014-10-28 15:25:22
  • 645

lua学习笔记---作用域

块,作用域全局和局部,默认情况下,为全局变量,除非特殊说明是局部代码中 do……end块内定义的变量无法被外部访问,同时任何在外围定义的局部变量也无法被内部访问。 强制转换 根据特定的转换规则(如果...
  • Jarlen
  • Jarlen
  • 2015-02-13 13:57:27
  • 1496

lua变量研究

--[[ In Lua, Global variables are accessible via the _G table ... ]] function tellme() for k,v ...
  • guang11cheng
  • guang11cheng
  • 2012-12-04 13:18:02
  • 2340

Lua的局部变量

Lua可以用local定义局部变量, 当
  • iicup
  • iicup
  • 2014-04-28 14:58:03
  • 7255

[lua] lua 函数 upvalue 数量限制

今天遇到一个报错: function at line xxx has more than 60 upvalues。查了一下,lua的upvalue是有上限的,这个上限定义在luaconf.h中: ...
  • n5
  • n5
  • 2014-08-20 11:47:04
  • 4425

Lua基础 基本介绍

1. Lua 命名规则 跟C语言一样,有字母数字下划线3个元素组合,不能以数字开头,下面这些命名都是合法的 i,  j,    i10,     _ij,      aSomewhatLongNa...
  • wzzfeitian
  • wzzfeitian
  • 2012-12-13 18:23:45
  • 11082

Lua初识之赋值-七

Lua初识之赋值 --[[a = "Hello" .. "World" print(a) m, n, num = 3, 6, 8  --可以一次给多个变量赋值 print("m = " .. m) -...
  • LIQIANGEASTSUN
  • LIQIANGEASTSUN
  • 2014-12-27 17:41:33
  • 1223
    个人资料
    等级:
    访问量: 8323
    积分: 153
    排名: 110万+
    最新评论