记于 2022 年 9 月 15 日
EMMC存储性能测试方法 - Wesley’s Blog
参考Android-emmc性能测试 | 一叶知秋进行实践操作
dd 命令
页面缓存
为了测试 emmc 的真实读写性能,我们需要先把页面缓存给清理:
echo 1 > /proc/sys/vm/drop_caches
console:/ # echo 1 > /proc/sys/vm/drop_caches
console:/ # busybox dd if=/dev/block/mmcblk0 of=/dev/null bs=1M count=512 <
512+0 records in
512+0 records out
536870912 bytes (512.0MB) copied, 2.491718 seconds, 205.5MB/s
console:/ # busybox dd if=/dev/block/mmcblk0 of=/dev/null bs=1M count=512 <
512+0 records in
512+0 records out
536870912 bytes (512.0MB) copied, 0.290948 seconds, 1.7GB/sconsole:/ # echo 1 > /proc/sys/vm/drop_caches
console:/ # busybox dd if=/dev/block/mmcblk0 of=/dev/null bs=1M count=512 <
512+0 records in
512+0 records out
536870912 bytes (512.0MB) copied, 2.508393 seconds, 204.1MB/s
console:/ #
连续执行两次 busybox dd if=/dev/block/mmcblk0 of=/dev/null bs=1M count=512
,从 /dev/block/mmcblk0 (即emmc) 块设备中读取内容,写到 /dev/null
。
/dev/null
是一个虚拟设备,写入这个路径并不会保存数据,可以认为这个设备的写入速度无限大,也就是写入速度不会成为这个命令的瓶颈,我们这个命令主要是为了测试 emmc 的读取速度。可以看到第一次执行的结果是 205.5MB/s,第二次执行的结果是 1.7GB/s。从这个数据来看,页面缓存极大的提高了热点文件的读取速度。然后我们用 echo 1 > /proc/sys/vm/drop_caches
命令清除一下页面缓存,再执行同样的 dd
命令,发现速度跟第一次差不多了。
写入性能测试
写入块设备
cache 分区一般是用来存放 OTA 升级包的,正常状态下挂载失败也不影响系统的正常运行,所以我们拿 cache 分区来作写入测试,先找到 cache 对应的块设备文件(df -h命令显示异常的话,可以执行ls -l /dev/block/platform/*/by-name/cache
)
注意:本测试方法可能会损坏cache分区导致ota失败,出现这种情况建议恢复出厂设置或者线刷。
console:/ # df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 1.5G 892K 1.5G 1% /dev
tmpfs 1.5G 0 1.5G 0% /mnt
/dev/block/mmcblk0p26 14M 168K 14M 2% /metadata
/dev/block/dm-1 1.1G 0.9G 199M 84% /
/dev/block/mmcblk0p40 379M 24M 356M 7% /wesley
/dev/block/mmcblk0p38 379M 154M 226M 41% /factory
/dev/block/mmcblk0p39 18M 1.3M 17M 8% /atv
/dev/block/mmcblk0p36 9.1M 24K 9.0M 1% /oem
/dev/block/dm-2 340M 240M 100M 71% /vendor
/dev/block/dm-0 167M 84K 167M 1% /mnt/scratch
overlay 167M 84K 167M 1% /system_ext
overlay 167M 84K 167M 1% /product
overlay 167M 84K 167M 1% /odm
tmpfs 1.5G 0 1.5G 0% /apex
tmpfs 1.5G 248K 1.5G 1% /linkerconfig
tmpfs 20M 1.0M 19M 6% /mnt/vendor/rtdlog
tmpfs 20M 8.0K 20M 1% /tmp
/dev/block/mmcblk0p23 1.4G 3.9M 1.4G 1% /cache
/dev/block/mmcblk0p31 236M 12M 224M 6% /mnt/vendor/tvconfigs
/dev/block/mmcblk0p32 26M 84K 26M 1% /mnt/vendor/tvdata
/dev/block/mmcblk0p33 18M 36K 18M 1% /mnt/vendor/impdata
/dev/block/mmcblk0p4 976K 228K 748K 24% /mnt/vendor/factory
/dev/block/mmcblk0p6 976K 28K 948K 3% /mnt/vendor/factory_ro
tmpfs 20M 0 20M 0% /shm
tmpfs 8.0M 0 8.0M 0% /mnt/EPGdb
/dev/block/mmcblk0p42 107G 4.8G 102G 5% /data
tmpfs 1.5G 0 1.5G 0% /data_mirror
/dev/fuse 107G 4.8G 102G 5% /mnt/user/0/emulated
console:/ #
cache分区的块设备文件为/dev/block/mmcblk0p23。
写入测试:
console:/ # echo 1 > /proc/sys/vm/drop_caches
console:/ # busybox dd if=/dev/zero of=/dev/block/mmcblk0p23 bs=1M count=1024 conv=fsync
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 11.371810 seconds, 90.0MB/s
输入文件为 /dev/zero,是一个虚拟设备,我们可以认为这个设备的读取速度无限大,也就是读取速度不会影响到写入的速度。
bs=1M : 一次写入 1M
count=1024 : 写入 1024 次,也就是写入的数据总量为 1G
conv=fsync : dd 结束前,把数据同步到 emmc,如果没加这个参数的话,数据可能还在缓存之中。为了确保数据准确,一定要加这个参数。
可以重复测试几次
写入文件
console:/ # echo 1 > /proc/sys/vm/drop_caches
console:/ # busybox dd if=/dev/zero of=/data/ddtest.bin bs=1M count=1024 conv=fsync
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 15.211609 seconds, 67.3MB/s
console:/ #
要重复测试几次。相对直接写块设备文件慢了 30M/s 左右。这可能是文件系统带来的影响。
读取测试
读取块设备
直接用我们上面介绍清除缓存的例子就行,这里就不再重复了。
从上面的例子得到的数据为 205M/s 左右。
读取文件
console:/ # echo 1 > /proc/sys/vm/drop_caches
console:/ # busybox dd if=/data/ddtest.bin of=/dev/null bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 5.464306 seconds, 187.4MB/s
console:/ #
直接拿测试写入速度时生成的文件,重复测试几次,速度基本上在 187MB/s 左右。
iozone
Android 系统源码中并没有 iozone,我们从官网上下载编译,我下载时最新版本为iozone3_493,这个版本已经有 Android.mk 在代码里面了,将源码放到 Android系统源码里面 mm 即可。下面已经是我编译好的文件。对应不同硬件使用对应版本即可,把文件push到/data/local/tmp/,并赋予执行权限。
source/izone.zip at main · wesley666/source
随机读写测试
console: echo 1 > /proc/sys/vm/drop_caches <
console:/data/local/tmp # ./iozone -azecI -+n -L64 -S32 -r1m -s1024m -i0 -i1 -i2 -w -f /data/iozonetest.bin Iozone: Performance Test of File I/OVersion $Revision: 3.493 $Compiled for 32 bit mode.Build: linux-arm Contributors:William Norcott, Don Capps, Isom Crawford, Kirby CollinsAl Slater, Scott Rhine, Mike Wisner, Ken GossSteve Landherr, Brad Smith, Mark Kelly, Dr. Alain CYR,Randy Dunlap, Mark Montague, Dan Million, Gavin Brebner,Jean-Marc Zucconi, Jeff Blomberg, Benny Halevy, Dave Boone,Erik Habbinga, Kris Strecker, Walter Wong, Joshua Root,Fabrice Bacchella, Zhenghua Xue, Qin Li, Darren Sawyer,Vangel Bojaxhi, Ben England, Vikentsi Lapa,Alexey Skidanov, Sudhir Kumar.Run began: Fri Jun 10 19:34:04 2022Auto ModeCross over of record size disabled.Include fsync in write timingInclude close in write timingO_DIRECT feature enabledNo retest option selectedRecord Size 1024 kBFile size set to 1048576 kBSetting no_unlinkCommand line used: ./iozone -azecI -+n -L64 -S32 -r1m -s1024m -i0 -i1 -i2 -w -f /data/iozonetest.binOutput is in kBytes/secTime Resolution = 0.000001 seconds.Processor cache size set to 32 kBytes.Processor cache line size set to 64 bytes.File stride size set to 17 * record size.random random bkwd record stride kB reclen write rewrite read reread read write read rewrite read fwrite frewrite fread freread1048576 1024 150737 0 210429 0 208681 173348 iozone test complete.
console:/data/local/tmp #
从结果来看,写速度为150MB/s,读速度为210MB/s,随机读速度为208MB/s。 随机写速度为 173MB/s。
重复测试几次结果差不多,读的速度基本跟 dd 的一致。写入比 dd 的快了一倍几,这里面的差距待研究,可能跟参数设置有关。
./iozone -azecI -+n -L64 -S32 -r1m -s1024m -i0 -i1 -i2 -w -f /data/iozonetest.bin [-Rb /sdcard/emmc_test.xls]
各个参数定义如下:
a: 使用全自动模式。生成涵盖所有测试操作的输出,记录大小为4k到16M,文件大小为64k到512M。
z: 与-a一起使用以测试所有可能的记录大小。通常,Iozone在全自动模式下使用时会忽略对非常大的文件的小记录大小的测试。此选项强制iozone在自动测试中也包括小记录大小。
e: 在时间计算中包括flush(fsync,fflush)
c: 在计时计算中包括close()。 仅当您怀疑当前正在测试的操作系统中的close()被破坏时,这才有用。 它对于NFS3测试也很有用,可以帮助识别nfs3_commit是否运行良好。
I: 对所有文件操作使用DIRECT I/O. 告诉文件系统所有操作都绕过缓冲区缓存并直接转到磁盘。 这也将在VxFS上使用VX_DIRECT,在Linux上使用O_DIRECT,在Solaris上使用directio()。
-+n: 没有选择重新测试。使用此选项可防止重新测试运行。
L64: Set processor cache line size to 64 Bytes
S32: Set processor cache size to 32KBytes
r2m: block size 指定一次写入/读出的块大小:1M
s1024m: 用于指定要测试的文件的大小:1024M
-i N 用来选择测试项, 比如Read/Write/Random 比较常用的是0 1 2,可以指定成-i 0 -i 1 -i2.这些别的详细内容请查man
0=write/rewrite
1=read/re-read
2=random-read/write
3=Read-backwards
4=Re-write-record
5=stride-read
6=fwrite/re-fwrite
7=fread/Re-fread
8=random mix
9=pwrite/Re-pwrite
10=pread/Re-pread
11=pwritev/Re-pwritev
12=preadv/Re-preadv
-+b 400000,30000: burst size 400000KBytes,sleep between burst 30000ms
w: 当临时文件使用完毕时不删除它们。把它们留在文件系统中。
f: 指定测试文件的名字(这个文件必须指定你要测试的那个硬件中)
可选参数:
R: Generate Excel report
b: Filename Create Excel worksheet file,emmc_test.xls
注意:
根据测试文件大小的不同,iozone 磁盘读写性能的测试方法主要包括1倍内存测试和2倍内存测试(避免缓存的影响)。
参考
Android-emmc性能测试 | 一叶知秋
axboe/fio: Flexible I/O Tester
DevriesL/RaptorMark
Iozone Filesystem Benchmark
iozone: Index of /src/current