December 14
最近在看CLI架构,发现CLI的许多设想,和俺的架构类似,都是面向堆栈虚拟机,模块化,支持按需加载模块,模块可以不在本机,当然它的模块分类比俺的细致,它区分了程序集模块(assembly)和模块,而我则就是一种模块。设计思想的不同之处在于:
- CLI设想的虚拟机执行机构只能是JITter(即时编译器),根本没有考虑解释器执行。
- CLI是强类型化的,所有的变量和类型都必须有Meta信息支持。
- CLI的VEE支持垃圾回收机制
- 将类放在VM中作为基本类型
- 所有的过程全是方法【如何处理类,类是特殊模块?】
计划:
- 重点分析它的模块架构,以资借鉴 【1周】
- 模块加载到内存后,它是如何管理代码地址空间的 【2周】
- 重新构造TurboScript的模块架构 【2周】
- 解决代码地址空间管理【2周】
- 脚本加载后将所有的相对地址全部重定位成绝对地址,构造 AddressResolver AddressBinding【1周】
- 分析类类型,如何实现
- 赋值指令和在类型之间值转换
- 错误异常处理机构【必须独立,方便更换,初期实现类似Delphi的异常错误处理机制】
- 类型对象变量的后期绑定机制
唉,事情真是一大堆啊。
December 05
最新评测结果如下
测试全部采用 QueryPerformanceCounter 高精度计数【Lua这个家伙不支持int64让我头疼了一阵,还好我想到了解决的方法】。
我这里测试指令:只简单测试加法运算;总共测试2017个加法指令与常数直接相加,最后的结果应该为:300*2017=605100
另外我还将测试子程序调用的速度。
没有比较是不行的,我用机器语言直接运行的效率和脚本相比:
下面是加法指令直接运行的速度:
x86汇编:
;计时开始
MOV EBX, 300 BB2C010000
ADD EBX, 300 81C32C010000
..... --- 总计 2017 次
ADD EBX, 300 81C32C010000
;计时结束
结果运行时间:60
Lua Script 脚本:
(计时开始)
local count = 300
count = count + 300
..... (总计 2017 次)
count = count + 300
(计时结束)
【Lua5.0.2】运行时间:110
【Lua5.1 】 运行时间: 120
EUPHORIA 加法指令顺序执行效率测试脚本:
--计时开始
count = 300
count +=300
..... --- 总计 2017 次
count +=300
--计时结束
结果运行时间:74
我写的 TurboScript 脚本:
(计时开始)
300
300 +
..... (总计 2017 次)
300 +
(计时结束)
结果运行时间:87 【比汇编慢0.31倍; 如果当我进一步取消CPUStates(判断终止标志位)测试,运行时间居然和汇编差不多了:61!嘿嘿。】
子过程调用的速度比较:
x86 汇编 子过程调用效率测试脚本:
function add(a,b: integer): integer;
asm
mov EAX, a
add EAX, b
end;
--计时开始
asm
mOV EAX, 300
MOV EDX, 300 CALL ADD
..... (总计 2017 次)
MOV EDX, 300 CALL ADD
--计时结束
结果运行时间:126
Lua Script 脚本:
function iAdd(a, b)
return a+b
end function
(计时开始)
local count = 300
count = iAdd(count, 300)
..... (总计 2017 次)
count = iAdd(count, 300)
(计时结束)
【Lua5.0.2】运行时间:1270
【Lua5.1 】 运行时间:1820
EUPHORIA 子过程调用效率测试脚本:
function iAdd(integer a, integer b)
return a+b
end function
--计时开始
count = 300
count = iAdd(count, 300)
..... --- 总计 2017 次
count = iAdd(count, 300)
--计时结束
结果运行时间:522 【比汇编慢了近0.759倍,比TurboScript 近调用慢近0.70倍】
TurboScript 子过程近调用效率测试
: Add +;
--计时开始
300
300 Add
..... (总计 2017 次)
300 Add
--计时结束
结果运行时间:157【只比汇编慢0.197倍,改用字节代码流后速度略有损失,现在的运行时间:169】
TurboScript 子过程模块之间的VM DLL远调用效率
: Add external 'test'; //该函数在另一文件中。
--计时开始
300
300 Add
..... (总计 2017 次)
300 Add
--计时结束
启用按需加载技术的结果运行时间:1082【不稳定徘徊在1082-8828】
使用的是按需加载技术,也就是仅当该函数被调用的时候才加载,然后加上Cache技术,后面的调用就在内存中处理。
时间远远长于其它,是因为加载文件耗去了绝大部分时间
不启用按需加载技术,而是预先加载模块:
结果运行时间:202 <如果不使用Cache功能每次都要查找所花时间:1790>
虽然编译通过,但是编译的脚本大小尺寸却和Delphi不一样,似乎FPC的某些类型大小与Delphi不一样。以后在看看,
以后要在FPC下编译解释器,就更要麻烦了,解释器核心全是嵌入汇编。
注意: FPC2.04版本下 CMP [EAX].TRec.F, $E9 和 CMP [EAX+TRec.F], $E9 含义不一致!用 -a 看生成的gnu汇编:
FPC 2.0.4 For i386
Target OS: Win32 for i386
Intel ASM
CMP BYTE PTR [EAX].TRec.F, $E9
cmpt $233,5(%eax)
CMP BYTE PTR [EAX+TRec.F], $E9
cmpb $233,5(%eax)
等全部能在FPC调试通过,那就基本上可以做到平台无关了。Delphi只支持win和Linux,遗憾。