Lua特性:
可移植性:使用clean C编写的解释器,可以在多个平台编译
良好的嵌入性:Lua提供很多API,可供宿主程序与Lua脚本之间进行通信和交换数据
非常小的尺寸:
Lua的效率很高:是速度最快的脚本语言之一
Lua源码大体分为三个部分:虚拟机核心、内嵌库以及解释器、编译器
Lua代码是通过翻译成Lua虚拟机能识别的字码运行,分为两大部分:
1.翻译代码以及编译为字节码的部分
2.Lua虚拟机相关的部分
GC(Garbage Collection,垃圾回收)
任何需要进行GC的Lua数据类型,必然以CommonHeader作为该结构体定义的最开始部分。可以将CommonHeader这个成员理解为一个基类的所有成员,而其他需要回收处理的数据类型均从这个基类继承下来,所以它们的结构体定义的开始部分就是这个成员。
GCObject这个联合体,将所有需要进行GC的数据类型全部囊括其中,这样定位和查找不同类型的数据时就方便多了。
Lua同时采用两种方式来做到数据统一。根据前面的分析,这表现在以下两个方面。
1.具体类型中CommonHeader,用来存放所有数据类型都通用的字段。
2.TValue作为统一表示所有数据的数据结构,内部使用了联合体Value将所有数据都包起来。
Lua字符串
1.在lua虚拟机中存在一个全局的数据区,用来存放当前系统中的所有字符串。
2.同一个字符串数据,在lua虚拟机中只可能有一份副本,一个字符串一旦创建,将是不可变更的。
3.变量存放的仅是字符串的引用,而不是其实际内容。
CommonHeader:存放所有数据类型都通用的字段。
reserved:这个变量用于标示这个字符串是否是lua虚拟机中的保留字符串。如果这个值为1,那么将不会再GC阶段被回收,而是一直保留在系统中。只有Lua语言中的关键字才会是保留字符串。
hash:该字符串的散列值。前面提到过,Lua的字符串比较并不会像一般的做法那样进行逐位对比,而是仅比较字符串的散列值。
len:字符串长度。
使用散列桶来存放数据,又有一个问题需要考虑:当数据非常大时,分配到每个桶上的数据也会非常多,这样一次查找也退化成了一次线性的查找过程。Lua中也考虑了这种情况,所以有一个重新散列(rehash)的过程,这就是当字符串数据非常多时,会重新分配桶的数量,降低每个桶上分配到的数据数量,这个过程在函数luaS_resize中
当新创建一个字符串TString,首先算散列值,全局变量,strt数组的索引值,如果已经有元素:使用链表串起来。global->State
->strt->hash
数量特别多时,会重新散列
新字符串:1.先找 2.有就复用 3.没有就新建
细节:字符串太长,会按一定步长取字符算散列值
复用时,GC标志修改为不需回收
所以,应该尽量少地使用字符串连接操作符,因为每一次都会生成一个新的字符串。可以用table来模拟缓存区,这样就避免多次连接操作符。