Archive for the ‘开源代码阅读’ Category

Lua的一个问题

最近对qnode进行压力测试,结果很不理想.前期只顾着赶功能,没有进行单元测试,只是简单的进行一些测试,所以现在打算回过头来对一些基础模块写测试用例.

这是本篇的题外话了,在压力测试qnode的时候,由于qnode是使用的actor模型,每个actor会有一个lua协程,但是在做压测的时候,会创建出很多actor这样就出了问题,来看看lua_newthread这个用来创建协程的函数:

LUA_API lua_State *lua_newthread (lua_State *L)

Lua5.1.4代码分析(二十四)-Lua GC原理

到了Lua GC部分,先简单介绍Lua GC的原理,后面再针对一些细节展开讨论。

Lua的GC算法使用的所谓“Mark And Sweep”算法。简单的理解,这个算法将GC分为两个阶段,一个是标记(mark)阶段,这一阶段将所有系统中引用的对象都逐一标记;而在清理(sweep)阶段,将把在mark阶段中没有被标记的数据删除。

在Lua中,使用几种颜色来区分不同的结点:
1)

自己动手实现Lua调试器

这段时间在qnode项目中新增了一个叫ldb的子项目,它的作用是使用C语言实现了一个lua调试器,后面将会在qnode中嵌入对调试lua脚本的支持。

先来简单提一下ldb的用法,在ldb目录的子目录test中,有一个main.c文件,其中使用ldb库提供的API实现对lua脚本的调试演示:

#include 
#include "ldb.h"

ldb_t *ldb;

static int
c_break(lua_State *state) {
 

Lua5.1.4代码分析(二十三)-如何实现Lua代码的热更新

能很好的支持代码热更新机制,是大部分选择要嵌入脚本语言的原因之一。好处很简单,脚本代码可以热更新的话,调试和线上解决问题都可以不用重启程序了,对开发效率有很大的帮助。

今天就来谈谈Lua代码如何实现热更新。

先简单回顾之前提过的模块和require机制。Lua内部提供了一个require函数,来实现模块的加载,它做的事情主要是以下几个:
1)

Lua5.1.4代码分析(二十二)-表的赋值和查询

这里涉及到的两个OPCODE,SETTABLE和GETTABLE,由名字可以知道,分别用于表的赋值和查询。
两个OPCODE指令格式如下:

OP_SETTABLE,/*  A B C R(A)[RK(B)] := RK(C)        */
OP_GETTABLE,/*  A B C R(A) := R(B)[RK(C)]      

Lua5.1.4代码分析(二十一)-表的创建和初始化

在讲解之前,先来简单回顾一下Lua表的初始化语法。

在Lua中,表是唯一的数据结构,可以使用它,模拟hash表,数组,链表,树等一切常用的数据结构。Lua表分为数组部分和hash部分。比如:

local t = {1,2,3,4,5}

以上分配一个Lua数组,依次为1到5.

而如果要初始化hash部分,则需要指定key,有两种方式:

local t = {a="test"}
local t =

学习Lua源代码的一些经验和参考资料推荐

断断续续在博客更新Lua5.1.4分析的一些文章,当前写的还是很杂乱。前面大体分析了一些数据结构(通用数据结构,表),一些流程的处理(赋值,逻辑跳转),还有函数相关的代码。后面还有不少没有分析到,目测还有表相关的操作,GC,Lua调试器等等,内容还是不少。

今天暂时打住,记录一下我看Lua代码这段历程来用到的一些知识点,经验和参考资料。

起初决定看Lua代码的理由很简单。每个对代码有点喜欢的人,都会觉得能创造一门语言是很酷而且充满神秘感的事情,尤其对我这样非科班出身的人。龙书很早就买了,一直搁着,上面布满了灰尘。中间也接触过一些编译类的书籍,比如编译原理与实践就实现了一个Toy级别的脚本语言,虽然五脏俱全,但是毕竟离正经产品级的代码还是有距离。

Lua也是一早就听说过,但是一直没有太多了解。直到2011年换工作之后,使用C++

Lua5.1.4代码分析(二十)-函数的返回参数

Lua中,函数的返回参数数量可能会随着赋值表达式左边的情况而进行调整。

比如,同样的函数f(),本来返回两个参数,而如果是表达式A = f(),则第二个返回参数将被抛弃。同样的,如果是表达式A,B,C =

简明Lemon核心代码分析二–向前看符号集的生成

所谓的向前看符号,就是当某一个项目的点号已经在最右边时,当下一个符号是什么符号时,可以使用该产生式进行归约操作。

比如,有一个项目是T→T*F·,它的向前看符号为=号,那么就意味着,如果当前栈的栈顶的符号为T*F,而下一个输入符号为=号时,可以使用产生式T→T*F进行归约操作,也就是将栈顶的T*F符号弹出,压入符号T=。

如果说,前面的buildshifts函数确定了不同的状态之间,经过哪些符号可以到达,那么向前看符号就决定了何时可以进行归约。要计算向前看符号,过程还是比较复杂,需要好几个辅助变量的计算。

首先要计算的是所有符号的first集合。它的算法,简单描述如下:

简明Lemon核心代码分析之一–LR(0)项目的生成

上一篇提到了Lemon这个项目,对于一个只有4000多行代码量的项目,用了一本400页的书来分析它的实现。我觉得应该把书读薄一点,所以我尝试着把这里我认为最核心的部分做一个我自己的诠释。

Lemon是一个LALR的语法分析器,有它自己自定义的语法规则,分析语法文件之后再根据模板文件输出C代码。这里涉及到几个步骤:词法分析,LALR语法分析,生成C代码文件。词法分析没有太多可说,就是根据语法规则定义状态机,提取词法的token,逐个进行分析。这个过程完毕之后,将产生相应的产生式,符号,产生式的左边符号,右边符号,开始符号等等这些都是在这一步完毕之后可以知道的。这一步不做太多的分析,因为相对而言还是比较简单的。而最后一步,也不做分析。重点在第二步,如何根据LALR算法得到动作表。

在我看来,核心包括两步:LR(0)项目的生成,以及每个LR(0)项目的向前看符号的计算。

首先看如何生成LR(0)项目。简单的说,是从开始符号出发,逐个遍历以它为产生式左边符号的产生式,逐个生成LR(0)项目。

Pages: 1 2 3 4 5 Next