读书笔记《Lua设计与实现》 了解Lua底层

来源:互联网 发布:js字符split 编辑:程序博客网 时间:2024/05/21 08:47

孙广东  2017.10.8

http://blog.csdn.NET/u010019717


十一抽时间看了这本书。

        还记得第一次接触Lua 是在2014年7月份, 当时还是在长春实习(Cocos Lua), 接触了一个多月就来北京开始了Unity


我是很喜欢看纸质书的,不太喜欢看电子书。 作者说这是第一本揭示Lua实现原理的图书。   这个历史就不了解了, 但是以前收藏过

《lua析》  https://wenku.baidu.com/view/c96a0e1055270722192ef772.html,         《readinglua云风的Lua源码赏析》.pdf    都是都是很早就有电子版本的。

说的有点跑偏,   要了解这些底层,还是最好有C/C++基础的好(专业会学到)。 大学还是学过编译原理,汇编语言的,  总之看完这本书还是对Lua有一个全新的认识。


Lua虚拟机 和 GC算法

1、 Java,  .Net 都是基于栈的虚拟机。  Lua是使用基于  寄存器的虚拟机。

2、 Lua 最多支持2^6 - 1 = 63 个指令。  这些指令类似于汇编指令。 

3、无论函数怎么执行,有多少函数,最终他们引用到的栈都是当前Lua虚拟机的栈 (这个栈在函数调用和 返回值的时候很重要)

4、 Lua词法

当时学习编译原理,  对一个语言进行解析一般是两遍遍历的过程: 第一遍解析源代码并生成抽象语法树(AST), 第二遍在将抽象语法树翻译为字节码。

但是Lua只进行一遍扫描。  这里就要提到  “递归下降法”  进行解析了。 

5、GC算法

       之前了解过 .Net 的GC.  《《读书笔记》C#/.Net 的托管堆和垃圾回收》   

书中也提到 引用计数标记清除算法

提到Lua 5.0 使用的是   双色标记清除算法,       提到Java , .Net 都存在的一个问题就是在GC过程中,程序必须暂停下来, 不能进行其他操作。   但是在Lua 5.1 开始解决了这个问题。  使用了 三色增量标记清除算法




跟踪指令解析和执行过程中常用的两个手段。

1) GDB调试

2) ChunkSpy  (LUA脚本动态反编译代码  http://chunkspy.luaforge.net/ ).   可以得到函数信息 指令,局部变量,常量等, 多层函数的嵌套关系



环境与模块

          看了这部分对作用域,  Lua热更新有帮助.

几个与环境相关的特殊变量----------Global表(G表)、 env表、 registry表以及 UpValue



字符串

        字符串在接触到的所有计算机语言中都是不可变的。  这是一个面试题啊, 为什么这样设计?

大概是这三点吧:

1. 字符串常量池的需要
字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。    (一种享元模式)
2. 允许String对象缓存HashCode
Java中String对象的哈希码被频繁地使用, 比如在hashMap 等容器中。
       字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码. 在String类的定义中有如下代码:
3. 安全性
       String被许多的Java类(库)用来当做参数,例如 网络连接地址URL,文件路径path,还有反射机制所需要的String参数等, 假若String不是固定不变的,将会引起各种安全隐患。



在Lua可以记住以下几点:

1)在Lua虚拟机中存在一个全局的数据区,用来存放当前系统中的所有字符串

2)同一个字符串数据,在Lua虚拟机中只可能有一份副本。

3)变量存放的仅是字符串的引用,而不是实际内容。

4)字符串比较实际上比较的是 字符串散列值(整数)


这里可以多提一嘴,就是 Golang的中的字符串, 因为当时学的时候  印象很深, Golang的string的所有操作的索引都是字符串的字节索引不是字符索引!!!


          表在Lua中太重要了, Lua使用表来统一表示Lua中的一切数据,  Lua的面向对象也是基于表实现的。

Lua的表分为数组部分 和 散列表部分。 其中数组部分的索引是从1开始的。

        这里就有一个问题了,   当我们以一个整数作为键值的数据写入Lua表时,并不确定是写入了数组还是散列表中???

自己看吧


在使用表时需要注意以下事项:

1)尽量不要将一个表混用数组和散列桶部分,即一个表最好只存放一类数据。

2)尽量避免进行重新散列操作, 因为重新散列操作的代价极大。  可以通过预分配,只使用数组部分等策略规避这个Lua解释器背后的动作, 能提升不少效率。


在 6.3 章节中,  有介绍表相关的操作指令

特别是介绍  “元表的实现原理” 和 面向对象!




Lua 源代码基本上都是采用纯 C 编写。

           想起大学时学习C语言,当时也并没有注意到   union  联合类型应用居然这么重要。  只知道struct结构体 复合数据很重要。






原创粉丝点击