type
status
date
slug
summary
tags
category
icon
password

在虚拟机中添加NVMe设备

由于我的虚拟机在创建的时候使用的是默认的设置,而默认设置中只会有一个SCSI硬盘,因此需要再为虚拟机额外添加一个NVMe磁盘设备(在配置之前需要关闭虚拟机)

添加NVMe设备

在需要安装NVMe设备的虚拟机界面中,点击“编辑虚拟机设置”
notion image
在弹出的界面中点击“添加”,并在新弹出的窗口中选择“硬盘”(NVMe是一个硬盘设备),然后点击下一步。
notion image
在弹出的窗口中选择NVMe
notion image
接下来的操作都是用来设定NVMe虚拟磁盘的存储方式的(比如是否需要新建一个虚拟磁盘、是使用一个文件描述该虚拟磁盘还是使用多个文件描述该虚拟磁盘),这个根据具体情况进行配置即可,这里就不再赘述了。
到这一步在/dev中就可以通过下面的指令找到nvme设备了:

NVMe磁盘分区

上面的操作相当于是为虚拟机创建了一个物理意义上的NVMe设备,接下来还需要为该设备创建分区
在终端中输入下面的指令,以使用fdisk为NVMe设备创建新分区
💡
这里的/dev/nvme0n1需要替换为实际的disk路径
在终端引导中输入“n”(new,表示新建分区)后,剩下的部分直接使用默认配置即可。
退出fdisk之后,使用下面的指令查看磁盘分区的情况
我的输出结果为:
notion image

挂载分区

在挂载分区之前需要先格式化分区,即将分区格式化为某个文件系统的格式。
在这里我希望NVMe磁盘分区的文件系统与原有虚拟机上的磁盘分区的文件系统一致,因此需要查看一下之前挂载在ubuntu根目录上的磁盘分区的文件系统是什么。可以使用以下指令查看所有磁盘分区的文件系统:
notion image
从这里可以发现sda磁盘中的sda3分区(即挂载在根目录上的磁盘分区)使用的文件系统为ext4。因此我也会将NVMe磁盘分区格式化为ext4文件系统。使用以下的指令将NVMe磁盘分区格式化:
格式化磁盘之后就可以再次使用lsblk -f 检查磁盘使用的文件系统。
接下来就是将磁盘挂载到一个挂载点上。
💡
挂载点实际上就是系统中的一个目录
使用以下指令可以将某一个磁盘的分区(即/dev/nvme0n1p1)挂载在/mnt/nvme挂载点上
接下来就可以使用df -h 指令查看NVMe设备是否挂载成功:
notion image
后面使用FIO的时候就可以直接在/mnt/nvme 目录中创建测试文件,即可测试NVMe硬盘的性能。

FIO的安装与使用

FIO的安装

这里直接把FIO的代码clone下来,然后按照Readme中Building部分进行安装即可:

FIO的使用

参考:
在使用FIO之前,需要先了解 一下FIO工具中各个参数的含义,以及FIO脚本如何编写

FIO参数

  • filename:测试文件名称,通常选择需要测试的盘的data目录(也可以直接指定文件的路径)。
    • 💡
      需要注意的是这个参数一定不能直接指定块设备,不然会导致文件系统损坏
  • direct:是否使用directIO,测试过程绕过OS自带的buffer,使测试磁盘的结果更真实。
    • 💡
      Linux读写的时候,内核维护了缓存,数据先写到缓存,后面再后台写到SSD。读的时候也优先读缓存里的数据。这样速度可以加快,但是一旦掉电缓存里的数据就没了。所以有一种模式叫做DirectIO,跳过缓存,直接读写SSD。
    • direct=1:表示使用directIO
    • direct=0:表示不使用directIO
  • rw:表示测试的读写类型
    • rw=randwread:测试随机读的I/O
    • rw=randwrite:测试随机写的I/O
    • rw=randrw:测试随机混合写和读的I/O
    • rw=read:测试顺序读的I/O
    • rw=write:测试顺序写的I/O
    • rw=rw:测试顺序混合写和读的I/O
  • bs:设定单次IO的块文件大小。如bs=4k,即设定单次IO的块文件大小为4k
  • bsrange:指定IO数据块的大小范围。如bsrange=512-2048,即指定IO数据块的大小范围为512-2048字节。
  • size:设定每个线程读写的数据量。如size=5G,表示每个线程读写的数据量为5G
  • numjobs:指定每个任务开多少个线程。如numjobs=1,就表示每个任务开1个线程
  • name:用于指定任务的名称。
    • 💡
      如果通过fio -name=job1 -name=job2指令,建立了两个任务,那么这两个任务将共享-name=job1之前的参数。-name=job2之后的就是job2任务独有的参数。
  • thread:表示使用线程进行测试(即使用pthread_create创建线程以执行测试任务)
    • 💡
      另一种是fork创建进程。但是由于进程的开销比线程要大,所以一般都采用thread测试。
  • runtime:用于指定测试时间。如runtime=1000表示测试时间为1000秒。
    • 💡
      如果不指定测试时间则会一直将size大小的文件分bs(或bsrange)每次写完后停止。
  • time_based:使用了这个参数后,如果在runtime指定的时间还没到时文件就被读写完成,将继续重复直到runtime时间结束。
  • ioengine:指定io引擎。实际上就是IO的方式
    • sync:使用标准的同步 I/O 操作(read 和 write 系统调用)。
    • libaio:Linux本地异步I/O。
    • mmap:使用内存映射 I/O(mmap 系统调用)。
    • posixaio:使用 POSIX 异步 I/O 接口(aio_read 和 aio_write)。
    • net:使用网络 I/O。
    • splice:使用 splice 系统调用进行零拷贝 I/O 操作。
    • 💡
      目前我认为这个IO引擎应该不是重点,所以没有更深入地去了解了
  • iodepth:指定IO队列的深度。如iodepth=16,就表示IO队列的深度为16。
    • 💡
      在异步模式下,CPU不能一直无限的发命令到SSD。比如SSD执行读写如果发生了卡顿,那有可能系统会一直不停的发命令,几千个,甚至几万个,这样一方面SSD扛不住,另一方面这么多命令会很占内存,系统也要挂掉了。这样,就带来一个参数叫做队列深度。这里的队列深度实际上跟NVMe SQ与CQ的队列深度的概念差不多。
  • rwmixwrite:用于指定在混合读写的模式下,写操作的占比。如rwmixwrite=30表示在混合读写的模式下,写操作占比为30%
    • 💡
      对应的还有一个rwmixread参数用于指示在混合读写模式下,读操作的占比。
  • group_reporting:关于显示结果的参数,表示汇总每个进程的信息(也就是各个任务的信息不会单独显示,在后面会遇到这个问题)
  • lockmem:设定用于测试的内存大小。lockmem=1g表示只使用1g内存进行测试。
  • zero_buffers:表示用0初始化系统buffer

FIO脚本

FIO脚本具有如下的基本格式:
其中各个部分的作用已经在注释中指出了,这里就不再赘述了。
作为一个脚本,在FIO脚本中同样可以使用变量,并且使用变量的方式与在Makefile中使用变量的方式是相同的,直接使用“$”即可使用变量。
编写的FIO脚本已经上传了github仓库:

结果分析

一般测试

使用fio脚本测试的结果也存放在了github仓库中:
参考:
在同步IO下,测试结果为:
IOPS
BW
LAT(AVG)
LAT(STDEV)
顺序读
4668
18.2MiB/s
427.56us
3350.10us
顺序写
5185
20.3MiB/s
383.72us
2847.53us
顺序读写(73)
3326+1424
13.0MiB/s+5699KiB/s
437.72us/377.62us
2484.57us/4487.09us
顺序读写(37)
1496+3489
5987KiB/s+13.6MiB/s
442.91us/381.59us
2383.66us/3168.40us
随机读
4408
17.2MiB/s
451.99us
3023.52us
随机写
5123
20.0MiB/s
387.67us
2924.31us
随机读写(73)
3163+1363
12.4MiB/s+5455KiB/s
477.38us/353.95us
2490.11us/4344.45us
随机读写(37)
1424+3329
5697KiB/s+13.0MiB/s
530.28us/371.11us
3151.14us/3148.85us
在异步IO下,测试结果为:
IOPS
BW
LAT(AVG)
LAT(STDEV)
顺序读
16.4k
64.1MiB/s
3323.12us
116024.89us
顺序写
3046
11.9MiB/s
20976.73us
626750.13us
顺序读写(73)
2136+914
8544KiB/s+3658KiB/s
20612.87us/21832.83us
617780.87us/647541.35us
顺序读写(37)
915+2133
3663KiB/s+8533KiB/s
19273.04us/21644.39us
590345.99us/641811.81us
随机读
21.1k
82.3MiB/s
2932.16us
64796.87us
随机写
3045
11.9MiB/s
20999.45us
626907.60us
随机读写(73)
2125+916
8502KiB/s+3665KiB/s
20949.02us/21164.18us
629906.01us/632482.49us
随机读写(37)
912+2133
3650KiB/s+8532KiB/s
19836.96us/21510.89us
600530.83us/639234.72us

随机写测试

进行随机写测试之前需要将磁盘格式化,格式化的过程就是先取消挂载,然后重新格式化文件系统,然后再挂载上去就好了,因此可以使用下面的指令进行格式化:
接下来就是重新编写一个fio脚本来测试随机写测试,脚本同样放在了仓库中:
测试数据如下:
1
7983KiB/s
16
7739KiB/s
2
8017KiB/s
17
7756KiB/s
3
7751KiB/s
18
7759KiB/s
4
7843KiB/s
19
7804KiB/s
5
7731KiB/s
20
7774KiB/s
6
7779KiB/s
21
7800KiB/s
7
7738KiB/s
22
7625KiB/s
8
7980KiB/s
23
7793KiB/s
9
7900KiB/s
24
6962KiB/s
10
7730KiB/s
25
7728KiB/s
11
7765KiB/s
26
7742KiB/s
12
7775KiB/s
27
7742KiB/s
13
7841KiB/s
28
7768KiB/s
14
7737KiB/s
29
8062KiB/s
15
7739KiB/s

杂记

  • iodepth与同步的IO引擎不可以同时使用,因为当IO引擎为同步引擎时,不会存在IO指令过多的情况,也就不用设定IO队列的深度了
    • 如果使用同步IO引擎并且iodepth≥1的话,就会弹出下面的信息:
  • 在fio中如果使用了group_reporting,并且没有使用new_group创建额外的分组的话,那么所有的任务都会归到同一个任务组中,这样最终输出信息的报告也会只有一个
 
Paper2PX4
Loading...
Noah
Noah
永远年轻,永远热泪盈眶
公告
❗❗复习笔记问题❗❗
由于兼容性问题
导入md文件可能导致了一些格式错误
🌹如发现格式错误,请联系我~🌹
🌹如博客内容有误也欢迎指出~🌹