LINUX IO 总结
磁盘通常是计算机最慢的子系统,也是最容易出现性能瓶颈的地方,因为磁盘离 CPU 距离最远而且 CPU 访问磁盘要涉及到机械操作,比如转轴、寻轨等。访问硬盘和访问内存之间的速度差别是以数量级来计算的,就像1天和1分钟的差别一样。要监测 IO 性能,有必要了解一下基本原理和 Linux 是如何处理硬盘和内存之间的 IO 的。
一.linux IO 中断
1.缺页中断
内存和硬盘之间的 IO 是以页为单位来进行的,在 Linux 系统上1页的大小为 4K。
Linux “内存” 包括物理内存和虚拟内存,虚拟内存(Virtual Memory)把计算机的内存空间扩展到硬盘,物理内存(RAM)和硬盘的一部分空间(SWAP)组合在一起作为虚拟内存为计算机提供了一个连贯的虚拟内存空间.
Linux利用虚拟内存极大的扩展了程序地址空间,使得原来物理内存不能容下的程序也可以通过内存和硬盘之间的不断交换(把暂时不用的内存页交换到硬盘,把需要的内存页从硬盘读到内存)来赢得更多的内存,看起来就像物理内存被扩大了一样。当程序启动的时候,Linux 内核首先检查 CPU 的缓存和物理内存,如果数据已经在内存里就忽略,如果数据不在内存里就引起一个缺页中断(Page Fault),然后从硬盘读取缺页,并把缺页缓存到物理内存里。缺页中断可分为主缺页中断(Major Page Fault)和次缺页中断(Minor Page Fault),要从磁盘读取数据而产生的中断是主缺页中断;数据已经被读入内存并被缓存起来,从内存缓存区中而不是直接从硬盘中读取数据而产生的中断是次缺页中断。
上面的内存缓存区起到了预读硬盘的作用,内核先在物理内存里寻找缺页,没有的话产生次缺页中断从内存缓存里找,如果还没有发现的话就从硬盘读取。很显然,把多余的内存拿出来做成内存缓存区提高了访问速度,缓存区越大预存的页面就越多,程序运行效率越高。
查看进程产生的缺页中断次数:cat /proc/$pid/stat
zhengfeilong@zfl-HP:~$ cat /proc/2016/stat
2016 (fcitx) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 0 0 0 -20 1 0 1656 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 0 0 0 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0
其中第10-13位分别对应:
min_flt=0 该任务不需要从硬盘拷数据而发生的缺页(次缺页)的次数
cmin_flt=0 累计的该任务的所有的waited-for进程曾经发生的次缺页的次数目
maj_flt=0 该任务需要从硬盘拷数据而发生的缺页(主缺页)的次数
cmaj_flt=0 累计的该任务的所有的waited-for进程曾经发生的主缺页的次数目
2.File Buffer Cache
Linux系统把多余的内存拿出来做成内存缓存区来提高程序访问速度。从上面的内存缓存区(也叫文件缓存区 File Buffer Cache)读取页比从硬盘读取页要快得多,所以 Linux 内核希望能尽可能产生次缺页中断(从文件缓存区读),并且能尽可能避免主缺页中断(从硬盘读),这样随着次缺页中断的增多,文件缓存区也逐步增大,直到系统只有少量可用物理内存的时候 Linux 才开始释放一些不用的页。例如要获取物理内存和文件缓存区的情况:
$cat /proc/meminfo:
MemTotal: 8119348 kB
MemFree: 1333676 kB
MemAvailable: 6009304 kB
Buffers: 2059668 kB
Cached: 1653252 kB
这台服务器总共有 8GB 物理内存(MemTotal),1.3GB 左右可用内存(MemFree),2GB 左右用来做磁盘缓存(Buffers),1.6GB 左右用来做文件缓存区(Cached),可见 Linux 真的用了很多物理内存做 Cache,而且这个缓存区还可以不断增长。
3.SWAP
当系统没有足够物理内存来应付所有请求的时候就会用到 swap 设备,swap 设备可以是一个文件,也可以是一个磁盘分区。( SWAP 交换分区是把物理磁盘当成内存的载体,也就是说:虽然使用 SWAP 可以让我们运行更多或更大的应用程序了,但物理磁盘的数据交换速度远比不上物理内存,因此也就可能造成运行性能的下降)。如果系统没有物理内存可用,就会频繁 swapping,如果 swap 设备和程序正要访问的数据在同一个文件系统上,那会碰到严重的 IO 问题,最终导致整个系统迟缓,甚至崩溃。swap 设备和内存之间的 swapping 状况是判断 Linux 系统性能的重要参考.
查看swap的使用情况:
$cat /proc/meminfo:
……
SwapTotal: 4096564 kB
SwapFree: 4096424 kB
……
二.Linux测试IO性能
1.测试IO读速度
hdparm:用于显示与设定硬盘的参数
执行命令:hdparm -t –direct /dev/sda1
输出结果:
/dev/sda1:
Timing O_DIRECT disk reads: 550 MB in 3.00 seconds = 183.31 MB/sec
注释:
-t :Perform device read timings
–direct :Use O_DIRECT to bypass page cache for timings
O_DIRECT :不使用缓存直接写入.
2.测试IO写速度
dd:用于指定大小/home/zhengfeilong/Desktop/linux_io.html的块拷贝一个文件,并在拷贝的同时进行指定的转换。
执行命令:sync;/usr/bin/time -p bash -c “(dd if=/dev/zero of=test.dd bs=1000K count=20000;sync)”
输出结果:
20000+0 records in
20000+0 records out
20480000000 bytes (20 GB) copied, 143.009 s, 143 MB/s
注释:
1.sync 命令用来刷新文件系统的缓冲区,执行sync命令实际的作用是把内存中的数据缓冲写入到磁盘中。
先执行下sync命令,是为了减少对后面测试的影响。也可以使用 echo 3 > /proc/sys/vm/drop_caches 来清除缓存。
2.time 命令用来测试命令的执行时间,shell内建还有一个time命令,我们这里使用全路径来指定使用的是非内建命令。
-p 选项设置时间的输出格式为POSIX缺省时间格式,单位是秒,在后面的测试小节可以看到time -p 的输出形式。
3.bash 命令 -c 选项的作用是将后面的字符串参数当作bash脚本来执行.
4.小括号的意思是另起一个子进程来执行括号中的脚本.
5./dev/zero该设备无穷尽地提供0,可/home/zhengfeilong/Desktop/linux_io.html以用于向设备或文件写入字符串0。
3.iozone
iozone(www.iozone.org)是一个文件系统的benchmark工具,可以测试不同的操作系统中文件系统的读写性能。可以测试 Read, write, re-read,re-write, read backwards, read strided, fread, fwrite, random read, pread, mmap, aio_read, aio_write 等等不同的模式下的硬盘的性能。
测试的时候请注意,设置的测试文件的大小一定要大过你的内存(最佳为内存的两倍大小),不然linux会给你的读写的内容进行缓存。会使数值非常不真实.
1.参数说明:
-i N 用来指定测试内容.
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
-R 产生execl格式的输出日志。
-b 将产生二进制的execl的日志文件名。
-s 测试的文件大小。
-r 文件块大小。
-a 在希望的文件系统上测试,不过只有-a的话会进行全面测试,要花费很长时间,最好用-i指定测试范围。
-g 设置自动模式下,指定最大测试文件大小。
-n 设置自动模式下,指定最小测试文件大小。
-f 指定测试文件,完成后会自动删除(这个文件必须指定你要测试的那个硬盘中)。
-F 指定临时文件组
-C 显示每个节点的吞吐量。
-t 并发数
-c 测试包括文件的关闭时间
-q 指定最大记录大小 例如 -q 512K
-y 指定最小记录大小 例如 -y 512K
2.测试实例
zhengfeilong@zfl-HP:~/iozone3_471/src/current$ ./iozone -a -i 1 -i 0 -i 2 -i 8 -c -g 16000m -n 1000M -Rab /tmp/iozone_test/tmpfs-iozone22.xls -f /tmp/iozone_test/iozone
输出结果:
WriterReport | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1024000 | 0 | 0 | 0 | 0 | 223280 | 207111 | 207412 | 219260 | 218093 | 222175 | 214415 | 219346 | 212156 |
2048000 | 0 | 0 | 0 | 0 | 171898 | 166677 | 164971 | 163712 | 165758 | 164018 | 165964 | 166860 | 165883 |
4096000 | 0 | 0 | 0 | 0 | 139747 | 151165 | 144033 | 145425 | 147765 | 149293 | 146913 | 146618 | 145710 |
8192000 | 0 | 0 | 0 | 0 | 133178 | 126834 | 152399 | 139238 | 131176 | 126845 | 136892 | 127782 | 140321 |
16384000 | 0 | 0 | 0 | 0 | 136729 | 134767 | 133852 | 139394 | 134735 | 125574 | 140512 | 137600 | 134339 |
Re-writerReport | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1024000 | 0 | 0 | 0 | 0 | 224938 | 213546 | 219517 | 216830 | 211730 | 185434 | 201497 | 162367 | 152384 |
2048000 | 0 | 0 | 0 | 0 | 163224 | 159739 | 167802 | 161970 | 158611 | 164316 | 159892 | 159591 | 160438 |
4096000 | 0 | 0 | 0 | 0 | 146974 | 151063 | 154612 | 149036 | 149420 | 139754 | 148469 | 148764 | 144612 |
8192000 | 0 | 0 | 0 | 0 | 132696 | 142852 | 158252 | 145361 | 142172 | 136946 | 139618 | 137814 | 145501 |
16384000 | 0 | 0 | 0 | 0 | 138767 | 136766 | 135149 | 141452 | 132109 | 132523 | 141165 | 139358 | 135391 |
ReaderReport | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1024000 | 0 | 0 | 0 | 0 | 7342718 | 7937183 | 7290531 | 7435591 | 7701051 | 7102185 | 6913452 | 6035208 | 5752549 |
2048000 | 0 | 0 | 0 | 0 | 7789290 | 7598297 | 7783792 | 6684358 | 7401148 | 6888845 | 6497583 | 5695329 | 5599879 |
4096000 | 0 | 0 | 0 | 0 | 862053 | 7968311 | 7873498 | 7766429 | 7828910 | 7547948 | 6920496 | 5929108 | 6059737 |
8192000 | 0 | 0 | 0 | 0 | 126679 | 143474 | 155767 | 142874 | 140990 | 135189 | 137295 | 135771 | 135460 |
16384000 | 0 | 0 | 0 | 0 | 137765 | 135236 | 136341 | 141884 | 136765 | 133308 | 142118 | 139285 | 135556 |
Re-readerReport | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1024000 | 0 | 0 | 0 | 0 | 8536244 | 8493553 | 8085971 | 7489426 | 8154999 | 8129299 | 7320141 | 6144869 | 5946932 |
2048000 | 0 | 0 | 0 | 0 | 8416414 | 8320767 | 7734228 | 7627870 | 7770765 | 8025929 | 7316923 | 6078052 | 6119957 |
4096000 | 0 | 0 | 0 | 0 | 8631973 | 8708943 | 8444649 | 8270404 | 8406258 | 8286464 | 7416785 | 6226020 | 6049855 |
8192000 | 0 | 0 | 0 | 0 | 129311 | 144253 | 156842 | 142559 | 138581 | 137788 | 137576 | 141982 | 141799 |
16384000 | 0 | 0 | 0 | 0 | 138180 | 136916 | 134872 | 140386 | 136058 | 133760 | 141880 | 139552 | 135400 |
RandomReadReport | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1024000 | 0 | 0 | 0 | 0 | 8282108 | 8224506 | 7966510 | 8202438 | 8277495 | 8051909 | 7221748 | 6056519 | 5877463 |
2048000 | 0 | 0 | 0 | 0 | 8056809 | 8048007 | 8203321 | 6561345 | 8168343 | 7845091 | 7287301 | 6177232 | 5910430 |
4096000 | 0 | 0 | 0 | 0 | 7948999 | 8270069 | 8190868 | 8289923 | 8407118 | 8266516 | 7407140 | 6106233 | 6169483 |
8192000 | 0 | 0 | 0 | 0 | 9526 | 18594 | 23618 | 54279 | 85990 | 111458 | 135329 | 159510 | 156702 |
16384000 | 0 | 0 | 0 | 0 | 7043 | 13311 | 22382 | 39803 | 61738 | 84983 | 111603 | 123806 | 129393 |
RandomWriteReport | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1024000 | 0 | 0 | 0 | 0 | 70674 | 71902 | 125892 | 145218 | 131121 | 149879 | 128880 | 206135 | 212983 |
2048000 | 0 | 0 | 0 | 0 | 31921 | 44124 | 74739 | 110187 | 116678 | 141066 | 147803 | 156084 | 160325 |
4096000 | 0 | 0 | 0 | 0 | 24993 | 36408 | 61918 | 90201 | 110463 | 119513 | 124539 | 138235 | 139422 |
8192000 | 0 | 0 | 0 | 0 | 17554 | 34154 | 55870 | 78730 | 101227 | 109139 | 109508 | 121577 | 130894 |
16384000 | 0 | 0 | 0 | 0 | 16221 | 32037 | 52270 | 75777 | 92394 | 98503 | 113466 | 118914 | 121461 |
解释测试报告:
“Writer report”
左侧一列是测试文件大小(Kbytes),最上边一行是记录大小,中间数据是测试的传输速度,拿第一行测试数据为例,测试文件为1024000k,以记录大小为64k传输,传输速度是223280Kbytes/s
关于各种测试的定义:
Write:
测试向一个新文件写入的性能。当一个新文件被写入时,不仅仅是那些文件中的数据需要被存储,还包括那些用于定位数据存储在存储介质的具体位置的额外信息。这些额外信息被称作“元数据”。它包括目录信息,所分配的空间和一些与该文件有关但又并非该文件所含数据的其他数据。拜这些额外信息所赐,Write的性能通常会比Re-write的性能低。
Re-write:
测试向一个已存在的文件写入的性能。当一个已存在的文件被写入时,所需工作量较少,因为此时元数据已经存在。Re-write的性能通常比Write的性能高。
Read:
测试读一个已存在的文件的性能。
Re-Read:
测试读一个最近读过的文件的性能。Re-Read性能会高些,因为操作系统通常会缓存最近读过的文件数据。这个缓存可以被用于读以提高性能。
Random Read:
测试读一个文件中的随机偏移量的性能。许多因素可能影响这种情况下的系统性能,例如:操作系统缓存的大小,磁盘数量,寻道延迟和其他。
Random Write:
测试写一个文件中的随机偏移量的性能。同样,许多因素可能影响这种情况下的系统性能,例如:操作系统缓存的大小,磁盘数量,寻道延迟和其他。
Random Mix:
测试读写一个文件中的随机偏移量的性能。同样,许多因素可能影响这种情况下的系统性能,例如:操作系统缓存的大小,磁盘数量,寻道延迟和其他。这个测试只有在吞吐量测试模式下才能进行。每个线程/进程运行读或写测试。这种分布式读/写测试是基于round robin 模式的。最好使用多于一个线程/进程执行此测试。
Backwards Read:
测试使用倒序读一个文件的性能。这种读文件方法可能看起来很可笑,事实上,有些应用确实这么干。MSC Nastran是一个使用倒序读文件的应用程序的一个例子。它所读的文件都十分大(大小从G级别到T级别)。尽管许多操作系统使用一些特殊实现来优化顺序读文件的速度,很少有操作系统注意到并增强倒序读文件的性能。
Record Rewrite:
测试写与覆盖写一个文件中的特定块的性能。这个块可能会发生一些很有趣的事。如果这个块足够小(比CPU数据缓存小),测出来的性能将会非常高。如果比CPU数据缓存大而比TLB小,测出来的是另一个阶段的性能。如果比此二者都大,但比操作系统缓存小,得到的性能又是一个阶段。若大到超过操作系统缓存,又是另一番结果。
Strided Read:
测试跳跃读一个文件的性能。举例如下:在0偏移量处读4Kbytes,然后间隔200Kbytes,读4Kbytes,再间隔200Kbytes,如此反复。此时的模式是读4Kbytes,间隔200Kbytes并重复这个模式。这又是一个典型的应用行为,文件中使用了数据结构并且访问这个数据结构的特定区域的应用程序常常这样做。许多操作系统并没注意到这种行为或者针对这种类型的访问做一些优化。同样,这种访问行为也可能导致一些有趣的性能异常。一个例子是在一个数据片化的文件系统里,应用程序的跳跃导致某一个特定的磁盘成为性能瓶颈。
Fwrite:
测试调用库函数fwrite()来写文件的性能。这是一个执行缓存与阻塞写操作的库例程。缓存在用户空间之内。如果一个应用程序想要写很小的传输块,fwrite()函数中的缓存与阻塞I/O功能能通过减少实际操作系统调用并在操作系统调用时增加传输块的大小来增强应用程序的性能。这个测试是写一个新文件,所以元数据的写入也是要的。
Frewrite:
测试调用库函数fwrite()来写文件的性能。这是一个执行缓存与阻塞写操作的库例程。缓存在用户空间之内。如果一个应用程序想要写很小的传输块,fwrite()函数中的缓存与阻塞I/O功能能通过减少实际操作系统调用并在操作系统调用时增加传输块的大小来增强应用程序的性能。这个测试是写入一个已存在的文件,由于无元数据操作,测试的性能会高些。
Fread:
测试调用库函数fread()来读文件的性能。这是一个执行缓存与阻塞读操作的库例程。缓存在用户空间之内。如果一个应用程序想要读很小的传输块,fwrite()函数中的缓存与阻塞I/O功能能通过减少实际操作系统调用并在操作系统调用时增加传输块的大小来增强应用程序的性能。
Freread:
这个测试与上面的fread类似,除了在这个测试中被读文件是最近才刚被读过。这将导致更高的性能,因为操作系统缓存了文件数据。几个特殊测试:
Mmap:
许多操作系统支持mmap()的使用来映射一个文件到用户地址空间。映射之后,对内存的读写将同步到文件中去。这对一些希望将文件当作内存块来使用的应用程序来说很方便。一个例子是内存中的一块将同时作为一个文件保存在于文件系统中。mmap文件的语义和普通文件略有不同。如果发生了对内存的存储,并不是立即发生相应的文件I/O操作。使用MS_SYNC 和MS_ASYNC标志位的msyc()函数调用将控制内存和文件的一致性。调用msync()时将MS_SYNC置位将强制把内存里的内容写到文件中去并等待直到此操作完成才返回。而MS_ASYNC置位则告诉操作系统使用异步机制将内存刷新到磁盘,这样应用程序可以直接返回而不用等待此操作的完成。这个测试就是测量使用mmap()机制完成I/O的性能。
Async I/O:
许多操作系统支持的另外一种I/O机制是POSIX 标准的异步I/O。本程序使用POSIX标准异步I/O接口来完成此测试功能。例如: aio_write(), aio_read(), aio_error()。这个测试测量POSIX异步I/O机制的性能。
三.Linux IO监控工具inotify-tools介绍
inotify-tools是为linux下inotify文件监控工具提供的一套c的开发接口库函数,同时还提供了一系列命令行工具,用来监控文件系统的事件。inotify-tools是用c语言编写的,除了需要内核支持inotify之外,不依赖其他。initify-tools提供了两种工具,一是inotifywait,用来监控文件或目录的变化。二是inotifywatch,用来统计文件系统访问的次数。
1.inotifywait
语法:inotifywait -mrq –timefmt ‘%d/%m/%y/%H:%M’ –format ‘%T %w %f’ -e modify,delete,create,attrib $path
输出结果:
2017-11-13 17:34 text.txt CREATE
2017-11-13 17:34 text.txt CLOSE_WRITE,CLOSE
2017-11-13 17:34 ttt.t MOVED_TO
2017-11-13 17:35 bb DELETE
参数说明:
-m是要持续监视变化。
-r使用递归形式监视目录。
-q减少冗余信息,只打印出需要的信息。
-e指定要监视的事件列表。
–timefmt是指定时间的输出格式。
–format指定文件变化的详细信息。
Events: 事件
access file or directory contents were read 文件或目录被(访问)读取r
modify file or directory contents were written 文件或目录被写入w
attrib file or directory attributes changed 文件或目录属性变更【理由:chmod更改属性】
close_write file or directory closed, after being opened in writeable mode 文件或目录被写关闭【理由:文件内容被更改】
close_nowrite file or directory closed, after being opened in read-only mode 文件或目录以只读方式打开后关闭
close file or directory closed, regardless of read/write mode 文件或目录被用编辑器(不管是读或写)关闭
open file or directory opened 文件或目录被用编辑器打开
moved_to file or directory moved to watched directory 文件或目录被移动进来【理由:mv目录内重命名】
moved_from file or directory moved from watched directory 文件或目录被移动出去
move file or directory moved to or from watched directory 文件或目录不管是移出或移进
create file or directory created within watched directory 文件或目录被创建【理由:mkdir创建目录】
delete file or directory deleted within watched directory 文件或目录被删除【理由:rm删除】
delete_self file or directory was deleted 文件或目录自删除
unmount file system containing file or directory unmounted 文件系统取消挂载
2.inotifywatch
语法:inotifywatch [-hvr] [-e] [-t] [-a] [-d] file1 [file2] [file3] […]
参数说明:
-h:输出帮助信息
-v:输出详细信息
-r:监视一个目录下的所有子目录
-t:设置超时时间
-e:只监听指定的事件
-a:以指定事件升序排列。
-d:以指定事件降序排列
示例:
创建一个目录,并监听该目录:
zhengfeilong@zfl-HP:~$ mkdir tmpdir
zhengfeilong@zfl-HP:~$ inotifywatch -v -e access -e modify -t 60 -r tmpdir/
Establishing watches…
Setting up watch(es) on tmpdir/
OK, tmpdir/ is now being watched.
Total of 1 watches.
Finished establishing watches, now collecting statistics.
Will listen for events for 60 seconds.
在另一终端,执行一下操作:
zhengfeilong@zfl-HP:~$ date > tmpdir/foo.txt
zhengfeilong@zfl-HP:~$ cat tmpdir/foo.txt
输出结果:
total access modify filename
5 3 2 tmpdir/