我做事喜欢结果导向,喜欢快速迭代,能10分钟搞定,绝对不愿意花15分钟。但是技术行当,还是得耐得住寂寞,因为很多事情10分钟搞不定,可能100分钟,1000分钟也搞不定,但是不代表我们真搞不定,需要花一些时间,花一些额外的代价来补课。水到渠成的时候,自己也得到了成长。
对于sysbench也是如此,里面用到了大量的lua模板,而且lua模板是sysbench压测的必备选项,所以我们要更好的理解它的实现逻辑,如果可以根据自己的需求来定制它的实现,使得符合真实业务,这种基准测试会更有意义。想到了这些,说干就干。
我们从sysbench的角度来理解Lua,开始Lua的学习旅程。
sysbench启动测试的时候,会在头部显示如下的信息:
sysbench 1.1.0 (using bundled LuaJIT2.1.0-beta3)
这句话信息量很大,我们可以慢慢分析,可以明显看到sysbench匹配的这个Lua是选用了LuaJIT,是一个beta版本。而如此一来,我们就需要确认两点,一个是Lua调用c的方法,在这里使用了LuaJIT,那么应该是使用ffi库来调用c了,否则一般是使用c的Lua C API这种方式。
这个信息可以在sysbench基础的lua文件中看到如下的内容印证。
local ffi = require("ffi")
接着第二个问题,系统层面是默认安装了Lua,基本上是5.1以上的版本,但是LuaJIT我们印象中是不曾安装过。安装sysbench的时候是否又安装了LuaJIT呢?我们使用find来简单验证一下,果然是默认安装了。
这是这个地方的引用是sysbench在脚本中绑定的路径,没有放到系统级的环境变量中。LuaJIT里调用c还是很流畅的,比如可以写一个简单的脚本,如下:
该例子参考了网络资源,执行结果如下:
然后我们就可以暂时先来系统的学习一下Lua,然后抓住要点之后再来看sysbench的代码就会容易多了。
先来一个最简单的Hello World
> print("Hello World!")
Hello World!
> print 'hello world'
hello world
Lua中的保留字有下面的这些:
and break do else
elseif end false for
function if in local
nil not or repeat
return then true until
while
如果要添加注释,有单行和多行,多行可以使用--[[ xxx --]]的方式来标注。
> -- this is a test comment --单行注释
> --[[ --多行注释
>> this is a test,line 1
>> this is a test comment line 2
>> this is a test comment line 3
>> --]]
如果变量b没有赋值,就会显示为nil,我们可以基于这个方式来处理一下变量值。
> print (b)
nil
> b=10
> print b --这种命名方式是不达标的
stdin:1: '=' expected near 'b'
> print(b)
10
然后就开始逐步有难度了。
我们看看学习套路之数据类型, Lua中有8个基本类型分别为:nil、boolean、number、string、userdata、function、thread和table。
要验证还是比较容易的,使用type方法即可。
> print (type('hello world'))
string
> print (type(10+3))
number
> print (type(print))
function
> print (type(type))
function
> print (type(nil))
nil
> print (type(true))
boolean
> print (type(type(x)))
string
遍历元组
如果有键值对这种形式的数据,可以通过循环映射的方式来返回,下面的两个实例,逻辑看起来是一样的,最后的输出还是有较大的差别。
> tab1 = {key1='val1',key2='val2','val3'}
> for k,v in pairs(tab1) do
>> print(k.."-"..v)
>> end
1-val3
key1-val1
key2-val2
> tab1 = {key1='val1',key2='val2',key3='val3'}
> for k,v in pairs(tab1) do
print(k.."-"..v)
end
key1-val1
key3-val3
key2-val2
关于类型转换,是在程序中很常见的一类处理方式,数值转换为字符型,或者字符型转换为数字,这一点上Lua的表现还不错。
> print("2" + 6)
8
> print('2' + 6)
8
>
> print ("2"+"6")
8
> print ("2+6")
2+6
> print ("-2e2"*"6")
-1200
> print ("error"+1)
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
stdin:1: in main chunk
[C]: ?
>
> print ("a".."b")
ab
> print(123..456)
stdin:1: malformed number near '123..456'
> print(123 .. 456)
123456
如果要计算字符的长度,可使用len方法或者变量的方式。
> len = "www.jeanron100.com"
> print(#len)
18
> print(#"www.jeanron100.com")
18
如果要初始化table,则可以使用如下的方式:
比如声明这样一个table a,然后赋值取值做数据处理,里面比较重要的就是下标的处理了,Lua的实现下标是从1开始。
> a = {}
> a["key"] = "value"
> key=10
> a[key]=100
> a[key]=a[key]+1000
> for k,v in pairs(a) do
>> print(k .. ":" .. v)
>> end
key:value
10:1100
如果要强化一下循环的部分,可以参考下面的例子,把fruits里的元素都循环输出。
[root@oel641 lua]# cat test1.lua
local fruits={'apple','orange','banana'}
for key,val in pairs(fruits) do
print("key",key)
end
[root@oel641 lua]# lua test1.lua
key 1
key 2
key 3
还有Lua中的函数,甚至支持匿名函数。
[root@oel641 lua]# cat test3.lua
function factorial1(n)
if n == 0 then
return 1
else
return n * factorial1(n-1)
end
end
print (factorial1(5))
factorial2=factorial1
print(factorial2(5))
这段代码和c非常相似,但是Lua里面比较有意思,函数可以更加灵活的使用,直接通过类似赋值的方式就搞定了,输出结果如下:
[root@oel641 lua]# lua test3.lua
120
120
大体测试了这些内容,随后会把sysbench代码里的逻辑总结出来。