专栏更新至今,四大基础模块的第三个模块——文件系统和磁盘 I/O 篇,咱们就已经学完了。很开心你尚未掉队,仍然在积极学习思考和实践操做,而且热情地留言与讨论。ios
今天是性能优化的第四期。照例,我从 I/O 模块的留言中摘出了一些典型问题,做为今天的答疑内容,集中回复。一样的,为了便于你学习理解,它们并非严格按照文章顺序排列的。数据库
每一个问题,我都附上了留言区提问的截屏。若是你须要回顾内容原文,能够扫描每一个问题右下方的二维码查看。缓存
在文件系统的工做原理篇中,我曾经介绍了阻塞、非阻塞 I/O 以及同步、异步 I/O 的含义,这里咱们再简单回顾一下。性能优化
首先咱们来看阻塞和非阻塞 I/O。根据应用程序是否阻塞自身运行,能够把 I/O 分为阻塞I/O 和非阻塞 I/O。bash
再来看同步 I/O 和异步 I/O。根据 I/O 响应的通知方式的不一样,能够把文件 I/O 分为同步I/O 和异步 I/O。网络
你能够看出,阻塞 / 非阻塞和同步 / 异步,其实就是两个不一样角度的 I/O 划分方式。它们描述的对象也不一样,阻塞 / 非阻塞针对的是 I/O 调用者(即应用程序),而同步 / 异步针
对的是 I/O 执行者(即系统)。数据结构
我举个例子来进一步解释下。好比在 Linux I/O 调用中,多线程
再如,在网络套接字的接口中,异步
在 文件系统原理 文章的最后,我给你留了一道思考题,那就是执行 find 命令时,会不会致使系统的缓存升高呢?若是会致使,升高的又是哪一种类型的缓存呢?工具
关于这个问题,白华和 coyang 的答案已经很准确了。经过学习 Linux 文件系统的原理,咱们知道,文件名以及文件之间的目录关系,都放在目录项缓存中。而这是一个基于内存
的数据结构,会根据须要动态构建。因此,查找文件时,Linux 就会动态构建不在缓存中的目录项结构,致使 dentry 缓存升高。
事实上,除了目录项缓存增长,Buffer 的使用也会增长。若是你用 vmstat 观察一下,会发现 Buffer 和 Cache 都在增加:
vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 1 0 7563744 6024 225944 0 0 3736 0 574 3249 3 5 89 3 0 1 0 0 7542792 14736 236856 0 0 8708 0 13494 32335 8 19 66 7 0 0 1 0 7494452 27280 272284 0 0 12544 0 4550 17084 5 15 68 13 0 0 1 0 7475084 42380 276320 0 0 15096 0 2541 14253 2 6 78 13 0 0 1 0 7455728 57600 280436 0 0 15220 0 2025 14518 2 6 70 22 0
这里,Buffer 的增加是由于,构建目录项缓存所需的元数据(好比文件名称、索引节点等),须要从文件系统中读取。
在 磁盘 I/O 延迟案例的最后,我给你留了一道思考题。
咱们经过 iostat ,确认磁盘 I/O 已经出现了性能瓶颈,还用 pidstat 找出了大量磁盘 I/O的进程。可是,随后使用 strace 跟踪这个进程,却找不到任何 write 系统调用。这是为何呢?
不少同窗的留言都准确回答了这个问题。好比,划时代和 jeff 的留言都指出,在这个场景中,咱们须要加 -f 选项,以便跟踪多进程和多线程的系统调用状况。
你看,仅仅是不恰当的选项,均可能会致使性能工具“犯错”,呈现这种看起来不合逻辑的结果。很是高兴看到,这么多同窗已经掌握了性能工具使用的核心思路——弄清楚工具
自己的原理和问题。
在 MySQL 案例的最后,我给你留了一个思考题。
为何 DataService 应用中止后,即便仍没有索引,MySQL 的查询速度仍是快了不少,而且磁盘 I/O 瓶颈也消失了呢?
ninuxer 的留言基本解释了这个问题,不过还不够完善。
事实上,当你看到 DataService 在修改 /proc/sys/vm/drop_caches 时,就应该想到前面学过的 Cache 的做用。
咱们知道,案例应用访问的数据表,基于 MyISAM 引擎,而 MyISAM 的一个特色,就是只在内存中缓存索引,并不缓存数据。因此,在查询语句没法使用索引时,就须要数据表
从数据库文件读入内存,而后再进行处理。
因此,若是你用 vmstat 工具,观察缓存和 I/O 的变化趋势,就会发现下面这样的结果:
vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st # 备注: DataService 正在运行 0 1 0 7293416 132 366704 0 0 32516 12 36 546 1 3 49 48 0 0 1 0 7260772 132 399256 0 0 32640 0 37 463 1 1 49 48 0 0 1 0 7228088 132 432088 0 0 32640 0 30 477 0 1 49 49 0 0 0 0 7306560 132 353084 0 0 20572 4 90 574 1 4 69 27 0 0 2 0 7282300 132 368536 0 0 15468 0 32 304 0 0 79 20 0 # 备注:DataService 从这里开始中止 0 0 0 7241852 1360 424164 0 0 864 320 133 1266 1 1 94 5 0 0 1 0 7228956 1368 437400 0 0 13328 0 45 366 0 0 83 17 0 0 1 0 7196320 1368 470148 0 0 32640 0 33 413 1 1 50 49 0 ... 0 0 0 6747540 1368 918576 0 0 29056 0 42 568 0 0 56 44 0 0 0 0 6747540 1368 918576 0 0 0 0 40 141 1 0 100 0 0
在 DataService 中止前,cache 会连续增加三次后再降回去,这正是由于 DataService 每隔 3 秒清理一次页缓存。而 DataService 中止后,cache 就会不停地增加,直到增加为
918576 后,就再也不变了。
这时,磁盘的读(bi)下降到 0,同时,iowait(wa)也下降到 0,这说明,此时的全部数据都已经在系统的缓存中了。咱们知道,缓存是内存的一部分,它的访问速度比磁盘快
得多,这也就能解释,为何 MySQL 的查询速度变快了不少。
从这个案例,你会发现,MySQL 的 MyISAM 引擎,自己并不缓存数据,而要依赖系统缓存来加速磁盘 I/O 的访问。一旦系统中还有其余应用同时运行,MyISAM 引擎就很难充分
利用系统缓存。由于系统缓存可能被其余应用程序占用,甚至直接被清理掉。
因此,通常来讲,我并不建议,把应用程序的性能优化彻底创建在系统缓存上。仍是那句话,最好能在应用程序的内部分配内存,构建彻底自主控制的缓存,好比 MySQL 的
InnoDB 引擎,就同时缓存了索引和数据;或者,可使用第三方的缓存应用,好比Memcached、Redis 等。
今天主要回答这些问题,同时也欢迎你继续在留言区写下疑问和感想,我会持续不断地解答。但愿借助每一次的答疑,能够和你一块儿,把文章知识内化为你的能力,咱们不只在实