Lua学习笔记

Lua是一种脚本编程语言,又被称为嵌入式的脚本语言。可以独立运行,也可以作为一个库,嵌入到宿主语言中。宿主语言需要创建Lua虚拟机加载Lua源码文件,虚拟机再将Lua代码转换为中间字节码并执行。

1.第一类值:lua当中函数是一个值,他可以存在变量中,可以作为函数参数,可以作为返回值

2.闭包:通过调用含有一个内部函数加上该外部函数持有的外部局部变量(upvalue)的外部函数(就是工厂)产生的一个实例函数,闭包组成:外部函数+外部函数创建的upvalue+内部函数(闭包函数)

3.pairs与ipair的区别:pairs会遍历table的所有键值对;ipairs就是固定地从key值1开始,下次key累加1进行遍历,如果key对应的value不存在,就停止遍历

4.require、dofile、loadfile的区别:(1).在加载一个.lua文件时,require会先在package.loaded中查找此模块是否存在,如果存在,直接返回模块;如果不存在,则加载模块文件。
(2).dofile读入代码文件并编译执行,每调用dofile一次,都会重新编译执行一次。
(3).loadfile:编译代码,将整个模块文件当成一个函数返回,但是不执行代码,dofile是对loadfile的一次包装。

5.Lua的垃圾回收是自动进行的,但是我们可以collectgarbage方法进行手动回收。

Lua学习笔记_第1张图片

尽量用局部变量,这样当其生命周期结束时,就能被回收;对于全局变量,可以根据使用情况置空,及时回收内存。另外,如果某些情况出现或即将出现内存占用过大的情况,可以考虑手动去进行垃圾回收。

6.Lua性能优化:(1).给table添加元素时,tab[#tab + 1] = a比table.insert(tab, a)效率高,远比table.insert(tab, 1, a)效率高;
(2).以局部变量代替多次使用的外部变量(config.XXX);
(3).减少函数调用可以很大提高效率;
(4).string.format比..效率低很多,但是GC会相对低一点,在大字符串连接中,应避免..。
(5).应用table来模拟buffer,然后concat得到最终字符串;
(6).3R原则:
(Reducing)避免创建新对象和节约内存。例如:如果你的程序中使用了太多的表,你可以考虑换一种数据结构来表示。
(Reusing)如果无法避免创建新对象,我们需要考虑重用旧对象。
(Recycling)Lua的垃圾回收器是一个增量运行的机制,即回收分成许多小步骤(增量的)来进行。频繁的垃圾回收可能会降低程序的运行效率。我们可以通过Lua的collectgarbage函数来控制垃圾回收器。

7.对元表的理解:给一个table关联元表 就是当你访问的这个table所访问的值不存在的时候 会返回默认的元表里的值 可以理解成面向对象里的继承 元表就是它的父类 如果本身有值就用本身的值 没值就用父类的值。

8.弱表:一个表是弱表,仅当
1. 该表有一个元表
2. 元表有成员__mode
3. __mode的取值为"k"或"v"或"kv",依次表示键是弱的,值是弱的或者键值都是弱的。

9.table序列化存储工具类

UserDataClass = Class()

local _table_insert = table.insert
local _tostring = tostring
local _string_format = string.format
local _pairs = pairs
local _type = type
local _table_concat = table.concat

local persistentDataPath = UnityEngine.Application.persistentDataPath

local function split_table(obj,str_tbl)
    if not str_tbl then
        str_tbl = {}
    end
    local t = _type(obj)
    if t == "number" then
        _table_insert(str_tbl, obj)
    elseif t == "boolean" then
        _table_insert(str_tbl, _tostring(obj))
    elseif t == "string" then
        _table_insert(str_tbl, _string_format("%q", obj))
    elseif t == "table" then
        _table_insert(str_tbl, "{\n")
        for k, v in _pairs(obj) do
            _table_insert(str_tbl, "[")
            split_table(k,str_tbl)
            _table_insert(str_tbl, "]=")
            split_table(v,str_tbl)
            _table_insert(str_tbl,",\n")
        end
        _table_insert(str_tbl, "}")
    elseif t == "nil" then
        return nil
    else
        error("can not serialize a " .. t .. " type.")
    end
    return str_tbl
end

function UserDataClass:_init(path)
    if not path then
        error("path is nil")
        return
    end

    self.path = persistentDataPath .."/"..path
    self.file = io.open(self.path,"r+")
    if self.file then
        local content = self.file:read("*a")
        self.data = self:UnSerialize(content)
    else
        self.file = io.open(self.path,"w+")
    end
    self.data = self.data or {}
end

function UserDataClass:_delete()
    self.file:close()
    self.path = nil
    self.data = nil
    self.file = nil
end

function UserDataClass:SetValue(key,info)
    self.data[key] = info
end

function UserDataClass:SaveFile()
    if self.file then
        self.file:seek("set")
        if self.file:write(self:Serialize(self.data)) == nil then
            return
        end
        self.file:flush()
    else
        print("file is not exist")
    end
end

function UserDataClass:GetValue(key)
    return self.data[key]
end

function UserDataClass:Serialize(obj)
    local t = split_table(obj)
    return _table_concat(t)
end

function UserDataClass:UnSerialize(lua)
    local t = _type(lua)
    if t == "nil" or lua == "" then
        return nil
    elseif t == "number" or t == "string" or t == "boolean" then
        lua = _tostring(lua)
    else
        error("can not unserialize a " .. t .. " type.")
    end
    lua = "return " .. lua
    local func = load(lua)
    if func ~= nil then
        return func()
    end
end

10.Lua配置表存储优化思路:配置表中大量的数据是重复的,或着是代表没有意义的空值(比如0,[]等);大量的中文字符串是需要游戏后期做本地化处理的;很多复合型数据(子表,数组)内容是一样的。优化方案:1.对于Excel中的一列,出现次数最多的值认定为默认值,然后把它从Lua表中剔除掉,然后利用metatable机制实现全局默认值存储;2.对于中文字符串,替换为一个唯一的id标识,写回到Lua表中,读取的时候加上相应的查找替换;3.对于一些复杂的子表或着数组,做唯一化替换处理,替换后写回到原始数据中;

12. Lua字符串存储:1.Lua中通过字符串的hash值来对字符串进行查找。2.Lua中的字符串变量存放的是字符串的引用,而不是字符串本身。3.同一个字符串在Lua虚拟机中只有一份。4.Lua虚拟机中global_State的strt字段存放着当前系统中的所有字符串。5.尽量避免循环拼接字符串,每拼接一次要创建一个新的字符串。

13.Lua多线程:单个 Lua 虚拟机只能工作在一个线程下,比较成熟的Lua多线程库有Lanes和Effilm,允许用户在不同的虚拟机间相互调用函数,大约是利用在虚拟机间同步函数的字节码和 upvalue 实现的。

14.Lua与C#交互主要是由Lua官方的提供的开源项目LuaInterface实现的,项目中提供了由C写的库文件,依靠C作为中间语言,维护一个虚拟栈,通过虚拟栈来实现数据交互,Slua/Ulua等基本都是借鉴LuaInterface库实现的。C#调用Lua需创建一个Lua虚拟机对象,虚拟机加载Lua文件并将其转换为字节执行。Lua调用C#需将C#源文件生成对应的Wrap文件,运行时Wrap文件会把C#方法字段注册到Lua虚拟机中,供Lua调用。

15.Lua协程拥有自己的独立的栈,局部变量,和指令; 所有协程都可以共享全局变量;协程不能像线程那样并行执行,协程之间需要相互协调执行,同一个时刻只能运行一个协程;Lua协程的实现

你可能感兴趣的:(Lua)