性能分析小案例系列,能够经过下面连接查看哦html
https://www.cnblogs.com/poloyy/category/1814570.htmllinux
前面有学到 Buffer 和 Cache 的概念:https://www.cnblogs.com/poloyy/p/13503848.htmlgit
咱们来简单复习下github
为了提高系统的 I/O 性能,它们利用内存,充当起慢速磁盘和快速 CPU 之间的桥梁,能够加速 I/O 的访问速度golang
既然 Buffer 和 Cache 对系统性能有很大影响,那咱们在软件开发的过程当中,能不能利用这 一点,来优化 I/O 性能,提高应用程序的运行效率呢? 答案天然是确定的docker
咱们想利用缓存来提高程序的运行效率,应该怎么评估这个效果呢?换句话说,有没有哪一个指标能够衡量缓存使用的好坏呢?ubuntu
独立的缓存模块一般会提供查询接口,方便咱们随时查看缓存的命中状况vim
不过 Linux 系统中并无直接提供这些接口,因此这里要介绍一下,cachestat 和 cachetop ,它们正是查看系统缓存命中状况的工具缓存
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD echo "deb https://repo.iovisor.org/apt/xenial xenial main" | sudo tee /etc/apt/sources.list.d/iovisor.list sudo apt-get update sudo apt-get install -y bcc-tools libbcc-examples linux-headers-$(uname -r)
vim /etc/profile # 在文件结尾处添加 export PATH=$PATH:/usr/share/bcc/tools # 保存文件后 source /etc/profile
# 它以 1 秒的时间间隔,输出了 3 组缓存统计数据 cachestat 1 3
cachetop
可使用 pcstat 这个工具,来查看文件在内存中的缓存大小以及缓存比例并发
# 安装 go apt install golang-go vim /etc/profile # 在文件结尾处添加 export GOPATH=~/go export PATH=~/go/bin:$PATH # 保存文件后 source /etc/profile go get golang.org/x/sys/unix go get github.com/tobert/pcstat/pcstat
pcstat /bin/ls
Cached 就是 /bin/ls 在缓存中的大小,而 Percent 则是缓存的百分比,看到它们都是 0,这说明 /bin/ls 并不在缓存中
执行 ls 命令,再来查看
ls pcstat /bin/ls
发现都在缓存中了
注意:没说第几个终端都是默认第一个终端执行命令哦
# 生成一个 512MB 的临时文件 dd if=/dev/sda1 of=file bs=1M count=512 # 清理缓存 echo 3 > /proc/sys/vm/drop_caches
pcstat file
确认刚刚生成的文件不在缓存中。若是一切正常, 会看到 Cached 和 Percent 都是 0
# 每隔 1 秒刷新一次数据 cachetop 1
dd if=file of=/dev/null bs=1M
能够看到 dd 命令并非全部的读都落到了磁盘上,读请求的缓存命中率只有 50%
dd if=file of=/dev/null bs=1M
磁盘的读性能蹭蹭蹭往上涨,去到了 1.6GB/s
能够发现,此次读的缓存命中率是 100%
pcstat file
测试文件已经被所有缓存起来了,和刚刚 cachetop 观察到缓存命中率 100% 是一致的
这两次结果说明,系统缓存对第二次 dd 操做有明显的加速效果,能够大大提升文件读取的性能。
从这里能够看到,每读取 32 MB 的数据,就须要花 0.9 秒
这个时间合理吗?这也太慢了吧,那这是否是没用系统缓存致使的呢?
读的命中率虽然是 100%,命中次数是 1024,看起来所有的读请求都通过了系统缓存
全都是缓存 I/O,读取速度不该该这么慢
这个案例估计没有充分利用系统缓存,若是系统调用设置直接 I/O 的标志,就能够绕过系统缓存
strace -p $(pgrep app)
它果真用了直接 I/O
删除 O_DIRECT 选项,让应用程序使用缓存 I/O ,而不是直接 I/O,就能够加速磁盘读取速度
查看新应用的日志
如今,每次只须要 0.03 秒,就能够读取 32MB 数据,明显比以前的 0.9 秒快多了。因此,此次应该用了系统缓存
为何优化前,经过 cachetop 只能看到不多一部分数据的所有命中,而没有观察到大量数据的未命中状况呢?
是由于,cachetop 工具并不把直接 I/O 算进来