fio

在写之前插个接口问题,自己还不清楚区别:

u2interface. msata interface.m2接口是sata简化接口。u2是新的接口,中间有突起,使用的是nvme协议,但是怎么使用的?数据线都没有 ,但是说是兼容好几种: 是否需要转换头也不知道。没使用过。


fio使用的时候,可以在ubuntu中使用sudo apt-get install  fio即可,而如果下载源码,那么wget http://brick.kernel.dk/snaps/fio-2.1.10.tar.gz(摘录其他人的博客)然后三步骤执行:./config      make     make install   如果想自己修改,那么可以修改完再次make  再次make install就会更换为新的版本。

fio简单的一次性命令为:fio -filename=/dev/sdb1 -direct=1 -iodepth=8 -thread -rw=read -ioengine=psync -bs=4k -size=100G -numjobs=30  -runtime=1000 -group_reporting -name=mytest

fio -output=磁盘路径

注意事项和说明:

1)测试只能测试设备不能测试一个设备中的文件目录。就是目录不能当成fio的测试对象.(这句话严重错误,可以测盘内文件的,也可以裸盘测试,即不带文件系统的测试,那样测完盘需要重新格式化。)

因此给出快速模拟出一个虚拟硬盘的方法,用于测试使用,步骤如下(注意使用dd命令没有-开头。。而fio中除了job file中写,命令行的参数前面必须有-)。 

dd if=/dev/zero  of=~/testforfio-4GB.img     bs=4M     count=1024

mkfs.ext4  testforfio-4GB.img 

sudo mount -o loop testforfio-4GB.img   ~/testforfio

此处需要强调:是使用testforfio-4GB.img挂载完了之后才会在df -h中显示出来/dev/loop0 这个设备就是将testforfio-4GB.img给使用/dev/loop0对应的驱动操作。所以不可以使用:  sudo mount -o loop   /dev/loop0   ~/testforfio

2)filename 是测试的盘符,direct=1表示绕过机器的buffer 不使用pagecache, rw=randwrite 或者randread或read 或write(不带rand的代表顺序读写)或者randrw表示随机读写 bs=4k表示单次io的块文件大小为4k. bsrange=512-2048表示指定了io块的大小范围。size=5G 表示该次测试总量的大小是5G(又有说明是每个进程跑5G的量??) numjobs表示使用线程是30个   runtime=100表示100秒结束,当然要与总量相比,如果不写runtime就是一次把5G总量写完为止。 ioengine=psync 表示io引擎使用psync方式  rwmixwrite=30表示混合读写下写占了30%  group_reporting  关于显示结果的,汇总每个进程信息,注意此处是汇总,而不是显示每个进程信息。如果想显示每个进程的如numjobs=5那么不用group_reporting就会将所有的信息显示5份然后加上最后的汇总如果用了group_reporting那么就是不会显示5份只有总的。 lockmem=1G 表示只使用1G内存进行测试  zero_buffers表示用0初始化buffer nrfiles=8表示每个进程生成文件数量。

对于低版本的fio2.多版本对于-group_reporting会出错,必须不加-才行。。。这个是版本错误。

另外写法中:–iodepth 2 或是 –iodepth=2.效果都是一样的。


如果想得到fio中每次io的lat时间,(当然clat和slat也能得到)。则在框架

在io_u.c文件中
static void io_completed(struct thread_data *td, struct io_u *io_u,

struct io_completion_data *icd)函数中

----------------------》

在io_u.c文件中

static void account_io_completion(struct thread_data *td, struct io_u *io_u,
  struct io_completion_data *icd,

  const enum fio_ddir idx, unsigned int bytes)

-------------------------》

add_lat_sample()中
add_stat_sample(&ts->lat_stat[ddir], usec);这个是要使用的。

add_log_sample(td, td->lat_log, usec, ddir, bs);这个不清楚用途

------------------------》

add_stat_sample()该函数处理的每次过来的数据与is也就是io_stat之间的比较。

对于fio详细的参数解释参考链接:http://blog.csdn.net/yuesichiu/article/details/8722417




job file格式采用经典的ini文件,语法如下。

[]表示job name 可以使用任何ascii字符,global除外,global section描述了job file中各个job默认的配置值。 而global下面的job section可以覆盖global section中的参数,一个job file可以包含几个global section而虽然有好几个,但是每个job都只会受它自身上面的global section影响。其中;  和#这两个符号用于注释使用。例子如下。

;-start job file-

[global]

rw=randread

size=128

[job1]


[job2]

;-end job file-

测试的时候直接使用fio 上述文件保存的文件名字即可。保存为disk-test     执行:fio  disk-test(注意此处就没有- 这个符号。来表明这是参数,而直接将其看成文件处理)

目前发现并没有可能来选择文件中不同的job section段来执行,只会做job 文件名  从上到下顺序执行job例如自己定义的test   5个线程和test1  1个线程   这两个job section执行完了以后汇总为   jobs=6 



对于libaio的使用说明:

libaio引擎会用这个iodepth值来调用io_setup准备个可以一次提交iodepth个IO的上下文,同时申请个io请求队列用于保持IO。
 在压测进行的时候,系统会生成特定的IO请求,往io请求队列里面扔,当队列里面的IO个数达到iodepth_batch值的时候,就调用io_submit批次提交请求,然后开始调用io_getevents开始收割已经完成的IO。 
 每次收割多少呢?由于收割的时候,超时时间设置为0,所以有多少已完成就算多少,最多可以收割iodepth_batch_complete值个。随着收割,IO队列里面的IO数就少了,那么需要补充新的IO。 

 什么时候补充呢?当IO数目降到iodepth_low值的时候,就重新填充,保证OS可以看到至少iodepth_low数目的io在电梯口排队着。

其中确实可以在fio代码中搜索到io_getevents这个函数,是系统调用,

Normally, with the libaio engine in use, fio will use the io_getevents system call to reap newly returned events.

就是说使用io_getevents系统调用来收割新的完成io。


但是是否出现使用ioengine=psync这种引擎,那么iodepth就没有用了。。只能使用numbjobs来提高并行性。从实验中证明确实加入多队列后速度明显快了,但是fio测试完写入是否将写入内容自动删除 ?(经测试,没有删除就是真实的写入。所以没有删除)因为自己挂载的loop0设备出现了structure needs cleaning.应该是写超容量了。(错误,此处不是写超了,因为真的写超了,测试结果中会有提示的。而是自己将filename设置为/dev/robusta之后就是将内容写入/dev/robusta,此时肯定会将整个盘上的文件系统给刷掉。那么为什么/media/robusta/test1又可以使用了?这么奇怪?不是说文件不行么?为什么,注意不是文件不行,而是文件夹不行,fio目的是将内容写入指定文件内,不会写入目录中。)  那么还有个问题,mkfs.ext4这种是格式化没挂载之前的盘,那么挂载mount执行了之后怎么办呢?

fio能够对裸设备(裸设备这个概念就很有迷惑性,什么是裸设备?就是没有文件系统的块设备,但是已经能够被操作系统识别为块设备了,只是没有挂载呢,因为即使mkfs.ext4了,没有挂载,一旦写入同样会将文件系统写坏。所以裸设备就是没挂载的块设备。),块设备,带文件系统设备都进行测试的。写入的内容不清楚是什么,用vi查看看不出来即使使用%!xxd也不行。但是如果说是读10MB,指定的文件是空的,那么竟然还能写入10M才能读?好奇怪。改成读20M那么就是写入了20M的东西再读了。。。也是醉了。

还有问题:设定的时间runtime与容量大小冲突以谁为准?  算了,网上的好多不能相信,并且有的是自己操作的还会有问题,比如可以使用文件,不能使用目录,让我因为只能使用裸盘测试呢。。如/dev/sda这种,其实用 /home/lxc/Music/text1就行,测试就能通过,不能通过的是识别快捷方式filename=~/Music/text1这样识别不了~而已。  并且上述问题,runtime与容量,设置的size是多大,那么fio就会将这个text1文件写成多大的,不论是只读还是只写,设定的size就是放在那的,与runtime也无关,而网上有的说只会写runtime时间的大小,应该不是这样的,是测试时间runtime,但是在测试前已经将size确定了。例如只读,给个text1空文件,那么仍然根据size大小写入数据然后read  runtime数量而已。所以size与runtime没有联系。只是确实有如果使用缓存的话太小的容量1G会被完全放在缓存中,对于测试有影响。所以一般使用direct=1将page cache给消除了。

但是上述仍然不严谨,例如另一种情况,当时间很长,但是size很小,不论是读还是写size都是20M那么时间设置成1个小时的纯读或者纯写,这样仍然是卡在20M就结束。其实其作用为:每次先设定size大小的块,然后不会重复操作,每次确定地对一个固定size操作。测试读或者写。所以当一整个size操作完了,那么runtime也就没用了,如果整个size在runtime内没有用完,那就是整个size已经存在了,只是测试时候测试runtime时间。

结:就是不管size 和runtime谁小。一直都是size在了,再按照runtime操作。时间多了扔掉,时间少了,按照时间内测试。但是size这个块一直存在于文件中被测试。

那么还有问题。在window中好像ntf格式,想格式化直接就带着文件系统格式化。而linux只有说当mount到文件夹上是挂载文件系统的,??那么mkfs.ext4是什么意思?这个不是使用mkfs.ext4格式化吗?如果是格式化,那么为什么不能直接对盘操作,要挂载在目录上才能操作?这个很奇怪。

使用dd生成的就是数据块,,与vi  1.txt效果是一样的,只不过dd if=/dev/zero是将of的值全部拷贝成0值。然后使用mkfs.ext2或则mkfs.ext4这样对普通文件进行格式化,可以生成文件系统的实际内容,用于研究,不用挂载就可以查看内容。

因此dd 使用后就是与vi  1.txt都是 普通文件属性可以看到是   - 不是  d 目录类型,只是将普通文件按照其大小使用loop 块设备方式以格式化成ext4文件格式挂载到文件夹中作为设备使用的。

而对于一个前面属性是b的更加可以操作了,因为其即使没有文件系统,但是由于挂载b这种块设备的时候已经设定了操作方式,所以操作他们也完全没有问题,而即使块设备格式化成ext4格式,也只是在其驱动设定的操作方式上面加了一层特定文件系统识别而已。所以对裸 b属性设备可以操作。

还有一个问题:   按道理对格式化后的b设备也可以操作。那么格式化后的b设备如果没有mount,那么操作是否正常?注意为了说明linux的格式化只能umount后再使用mkfs.ext4,直接对挂载的设备进行mkfs操作,提示:/dev/xxx   is mounted , will not make a filesystem here。

所以挂载后的设备再次格式化就需要umount --mkfs--mount后重新使用。

另外一个问题,操作入口:如果没有从文件系统入口进入,而直接对文件操作,对自己mkfs.ext4 ext4-2M 后的文件直接进行写入或者对块设备从头到尾开始写入,那么就会将文件系统冲掉,而只有从挂载后文件系统可见的入口开始写才能不冲掉文件系统。所以要挂载,你不挂载就开始写,也能写,虽然将文件系统冲掉,这样的写入没有意义。

所以实验如下:模拟的或者真实的只要属性能够显示是b的设备文件,即使做过mkfs.ext4,但是不挂载(不挂载就叫裸)直接写入数据就将格式化 的好好的文件系统给冲坏了。只有挂载了,从目录层面进入的写入,才会按照文件系统的管理来使用。所以只要目标是设备文件/dev/xxx那么都是原始写入,不是从ext4文件系统层面写入。都会破坏文件系统自身的。因此关于OCSSD中rockdb的应用,其打开路径以及打开方式不可能是有mount,只能是对设备路径/dev/xxx操作数据流。


还有个问题,linux中午format命令,format命令在dos中在vxworks中见过,或者更准确的说format在vxworks中是用户自己封装的一个函数?在linux中没有windows中一键将硬盘格式化的,在linux中只能先umount然后mkfs.ext4然后再次mount.而且mkfs.ext4命令叫做linux的格式化。  倒是可以在linux中不格式化,直接将卡中的内容完全rm删除掉,也算是一种格式化吧,只是删除操作与window都一样,一步就可以操作了。

总结:linux只要系统能够识别属性,那么内核就可以很只能地识别对象(这个机制就是很特别,与linux把一切都看成文件,这些信息都在文件结构体里面的。),然后根据对象使用不同的操作函数,先不说管道之类的,仅仅三种,目录,文件,设备,这三种都能智能识别,所以不同操作产生不同结果。


对于两种模拟块设备的说明。

1、一种是自己编写ramdisk,驱动,然后insmod后就会有一个属性为b的块设备了。

2、一种是使用普通的文件,这个文件格式化成mkfs.ext4 然后借用linux自带的loop设备驱动?(暂时这样理解loop),来对这个文件区域模拟成块设备操作。所以这个mount文件的时候使用的是mount -o loop   自己设定的文件  目录  

这样mount后df -h 会出现一个/dev/loop0的设备,就是模拟块设备成功了。




注意,fio的问题:

输出解读:Disk stats (read/write):

sda: ios=16398/16511, merge=30/162, ticks=6853/819634, in_queue=826487, util=100.00%

这个意思是:

Each value is printed for both reads and writes, with reads first.

ios Number of I/Os performed by all groups.
merge Number of merges performed by the I/O scheduler.
ticks Number of ticks we kept the disk busy.
in_queue Total time spent in the disk queue.
util The disk utilization. A value of 100% means we kept the disk busy constantly, 50% would be a disk idling half
of the time.




此处解答所有关于fio的疑问

fio的sync这种前端操作与磁盘之间,还夹着pagecache,给人感觉是只要是sync一定是第一个io结束了才有第二个io,没错,从计算机前端,fio应用上看是这样的,但是计算机得到信息还可以从缓存中得到,写入也可以先写入缓存中,就是缓存将前端和盘进行了隔离,如果使用sync但是不用direct=1那么出现的问题是:前端使用的就是sync,带上缓存中的信息,保证前端就是接收到第一个io值再发第二个io值,而所有io实际都经过换存和调度处理了,这样卡上接收到的是处理过的就不一定是sync类型的io了,甚至都不是两个io了,可能拆分可能合并等。所以别看sync,没有了direct的保证,同样不能保证是在disk上的sync。而sync后direct=0时候,可以做到晚会再真正写到盘里,甚至读的时候,最终也不会读盘内的信息,盘的打印信息是没有读的消息的,所以测试盘就最好所有的情况下都加上direct=1来处理。当然这时候要考虑对齐问题,毕竟非单位数据会出错的。最小单位是4k.(bdbm中,不同设备格式化结果不同。)

你可能感兴趣的:(linux,fio)