性能分析(7)- 未利用系统缓存导致 I/O 缓慢案例
性能分析小案例系列,可以通过下面链接查看哦
https://www.cnblogs.com/poloyy/category/1814570.html
前提
前面有学到 Buffer 和 Cache 的概念:https://www.cnblogs.com/poloyy/p/13503848.html
我们来简单复习下
Buffer 和 Cache 的设计目的
为了提升系统的 I/O 性能,它们利用内存,充当起慢速磁盘和快速 CPU 之间的桥梁,可以加速 I/O 的访问速度
Buffer 和 Cache
- BUffer:对磁盘的读写数据缓存
- Cache:对文件系统的读写数据缓存
读写角度
- 从写的角度来说,不仅可以优化磁盘和文件的写入,对应用程序也有好处,应用程序可以在数据真正落盘前,就返回去做其他工作
- 从读的角度来说,不仅可以提高那些频繁访问数据的读取速度,也可以降低频繁 I/O 对磁盘的压力
引入主题
既然 Buffer 和 Cache 对系统性能有很大影响,那我们在软件开发的过程中,能不能利用这 一点,来优化 I/O 性能,提升应用程序的运行效率呢? 答案自然是肯定的
缓存命中率
灵魂拷问
我们想利用缓存来提升程序的运行效率,应该怎么评估这个效果呢?换句话说,有没有哪个指标可以衡量缓存使用的好坏呢?
灵魂回答
- 缓存命中率
- 指直接通过缓存获取数据的请求次数,占所有数据请求次数的百分比【使用缓存请求次数 / 总请求次数】
- 命中率越高,表示使用缓存带来的收益越高,应用程序的性能也就越好
缓存的重要性
- 缓存是现在所有高并发系统必需的核心模块
- 主要作用:把经常访问的数据(热点数据),提前读入到内存中,下次访问时就可以直接从内存读取数据,而不需要经过硬盘,从而加快应用程序的响应速度
cachestat、cachetop
独立的缓存模块通常会提供查询接口,方便我们随时查看缓存的命中情况
不过 Linux 系统中并没有直接提供这些接口,所以这里要介绍一下,cachestat 和 cachetop ,它们正是查看系统缓存命中情况的工具
- cachestat 提供了整个操作系统缓存的读写命中情况
- cachetop 提供了每个进程的缓存命中情况
Ubuntu 安装工具
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
cachestat
# 它以 秒的时间间隔,输出了 组缓存统计数据
cachestat
字段说明
cachetop
cachetop
- 默认按照缓存的命中次数(HITS)排序,展示了每个进程的缓存命中情况
- 具体到每一个指标,这里的 HITS、MISSES 和 DIRTIES ,跟 cachestat 里的含义 一样,分别代表间隔时间内的缓存命中次数、未命中次数以及新增到缓存中的脏页数
- READ_HIT:读的缓存命中率
- WRITE_HIT:写的缓存命中率
查看文件的缓存大小
可以使用 pcstat 这个工具,来查看文件在内存中的缓存大小以及缓存比例
安装 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
pcstat /bin/ls
Cached 就是 /bin/ls 在缓存中的大小,而 Percent 则是缓存的百分比,看到它们都是 0,这说明 /bin/ls 并不在缓存中
执行 ls 命令,再来查看
ls
pcstat /bin/ls
发现都在缓存中了
讲案例前的准备
- 系统:Ubuntu 18.04,当然同样适用于其他的 Linux 系 统。
- 机器配置:2 CPU,2 GB 内存
- 预先按照上面的步骤安装 bcc 和 pcstat 软件包,并把这些工具的安装路径添加到到 PATH 环境变量中
- 预先安装 Docker 软件包: apt-get install docker.io
- 打开两个终端同时连到 Linux 上
案例一:通过 dd 写入读取文件
注意:没说第几个终端都是默认第一个终端执行命令哦
dd 命令生成一个临时文件
# 生成一个 512MB 的临时文件
dd if=/dev/sda1 of=file bs=1M count= # 清理缓存
echo > /proc/sys/vm/drop_caches
运行 pcstat 查看 file 文件
pcstat file
确认刚刚生成的文件不在缓存中。如果一切正常, 会看到 Cached 和 Percent 都是 0
运行 cachetop
# 每隔 秒刷新一次数据
cachetop
第二个终端运行 dd 命令
dd if=file of=/dev/null bs=1M
- 从 dd 的结果可以看出,这个文件的读性能是 639 MB/s
- 由于在 dd 命令运行前我们已经清理了缓存,所以 dd 命令读取数据时,肯定要通过文件系统从磁盘中读取
查看 cachetop
可以看到 dd 命令并不是所有的读都落到了磁盘上,读请求的缓存命中率只有 50%
第二个终端再次运行 dd 命令
dd if=file of=/dev/null bs=1M
磁盘的读性能蹭蹭蹭往上涨,去到了 1.6GB/s
再查看 cachetop
可以发现,这次读的缓存命中率是 100%
第二个终端运行 pcstat
pcstat file
测试文件已经被全部缓存起来了,和刚刚 cachetop 观察到缓存命中率 100% 是一致的
总结
这两次结果说明,系统缓存对第二次 dd 操作有明显的加速效果,可以大大提高文件读取的性能。
案例二
前提
- 这里运行了一个不可中断状态的进程
- 功能:是每秒从磁盘分区 /dev/sda1 中读取 32MB 的数据, 并打印出读取数据花费的时间
查看应用日志
从这里可以看到,每读取 32 MB 的数据,就需要花 0.9 秒
灵魂拷问
这个时间合理吗?这也太慢了吧,那这是不是没用系统缓存导致的呢?
查看 cachetop
结果分析
读的命中率虽然是 100%,命中次数是 1024,看起来全部的读请求都经过了系统缓存
灵魂又拷问了
全都是缓存 I/O,读取速度不应该这么慢
深入分析
- 另一个重要因素,每秒实际读取的数据大小,HITS 代表缓存的命中次数,那么每次命中能读取多少数据呢?自然是一页
- 内存以页为单位进行管理,而每个页的大小是 4KB
- 所以,在 5 秒的时间间隔 里,命中的缓存为 1024*4K/1024 = 4MB,再除以 5 秒,可以得到每秒读的缓存是 0.8MB,显然跟案例应用的 32 MB/s 相差太多
结果猜想
这个案例估计没有充分利用系统缓存,如果系统调用设置直接 I/O 的标志,就可以绕过系统缓存
通过 strace 观察系统调用
strace -p $(pgrep app)
结果分析
- 从 strace 的结果可以看到,案例应用调用了 openat 来打开磁盘分区 /dev/sdb1,并且传 入的参数为 O_RDONLY|O_DIRECT(中间的竖线表示或)
- O_RDONLY 表示以只读方式打开
- 而 O_DIRECT 则表示以直接读取的方式打开,这会绕过系统的缓存
- 验证了这一点,就很容易理解为什么读 32 MB 的数据就都要那么久了
- 直接从磁盘读写的速度,自然远慢于对缓存的读写,这也是缓存存在的最大意义了
查看应用源码
它果然用了直接 I/O
修改源代码
删除 O_DIRECT 选项,让应用程序使用缓存 I/O ,而不是直接 I/O,就可以加速磁盘读取速度
验证修复后的应用
查看新应用的日志
结果分析
现在,每次只需要 0.03 秒,就可以读取 32MB 数据,明显比之前的 0.9 秒快多了。所以,这次应该用了系统缓存
再次查看 cachetop
结果分析
- 果然,读的命中率还是 100%,HITS (即命中数)却变成了 40960
- 同样的方法计算一 下,换算成每秒字节数正好是 32 MB(即 40960*4k/5/1024=32M)
总结
- 在进行 I/O 操作时,充分利用系统缓存可以极大地提升性能。
- 但在观察缓存命中率时,还要注意结合应用程序实际的 I/O 大小,综合分析缓存的使用情况
扩展
为什么优化前,通过 cachetop 只能看到很少一部分数据的全部命中,而没有观察到大量数据的未命中情况呢?
回答
是因为,cachetop 工具并不把直接 I/O 算进来
性能分析(7)- 未利用系统缓存导致 I/O 缓慢案例的更多相关文章
- 性能分析(3)- 短时进程导致用户 CPU 使用率过高案例
性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 系统架构背景 VM1:用作 Web 服务器,来模拟 ...
- 性能分析(1)- Java 进程导致 CPU 使用率升高,问题怎么定位?
性能分析小案例系列,可以通过下面链接查看哦 ps:这些分析小案例不能保证百分比正确,是博主学习过程中的总结,仅做参考 前提 本机有一个很占用 CPU 的项目,放在了 Tomcat 下启动着 如何定位 ...
- 性能分析(2)- 应用程序 CPU 使用率过高案例
性能分析小案例系列,可以通过下面链接查看哦 https://www.cnblogs.com/poloyy/category/1814570.html 系统架构背景 其中一台用作 Web 服务器,来模拟 ...
- JVM性能分析 | 一次生产系统Full GC问题分析与排查总结
一次生产系统Full GC问题分析与排查总结 背景 最近某线上业务系统生产环境频频CPU使用率过低,频繁告警,通过重启可以缓解,但是过了一段时间又会继续预警,线上两个服务节点相继出现CPU资源紧张,导 ...
- 性能分析 | Java进程CPU占用高导致的网页请求超时的故障排查
一.发现问题的系统检查: 一个管理平台门户网页进统计页面提示请求超时,随进服务器操作系统检查load average超过4负载很大,PID为7163的进程占用到了800%多. 二.定位故障 根据这种故 ...
- KingbaseES V8R3 由于修改系统时间导致sys_rman备份故障案例
案例说明: 此案例,为复现"current time may be rewound"错误.对于数据库环境,在使用前必须保证系统时间的正确性.如果数据库创建后,再将系统时间修改为 ...
- Linux服务器性能分析与优化
影响服务器性能的因素: CPU :大部分cpu在同一时间只能运行一个线程,超线程的处理器可以在同一时间处理多个线程,因此可以利用超线程特性提高系统性能. 在linux系统下,只有运行SMP内核才能支持 ...
- 系统级性能分析工具perf的介绍与使用[转]
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...
- 系统级性能分析工具perf的介绍与使用
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...
随机推荐
- 利用Serverless应用搭建Hexo博客
本文将介绍如何使用火爆的Serverless应用,15分钟快速搭建Hexo博客.以腾讯云提供的Serverless应用–云开发为例: 步骤1:安装 CloudBase CLI 以及本地部署 Hexo ...
- 题解 洛谷 P3210 【[HNOI2010]取石头游戏】
考虑到先手和后手都使用最优策略,所以可以像对抗搜索一样,设 \(val\) 为先手收益减去后手收益的值.那么先手想让 \(val\) 尽可能大,后手想让 \(val\) 尽可能小. 继续分析题目性质, ...
- 题解 CF997E 【Good Subsegments】
先将问题进行转化,发现满足\((max-min)-(r-l)=0\)的区间即为好区间. 对于本题这样的统计子区间的问题,先将询问离线,按右端点排序一个一个解决,固定右端点,然后通过数据结构来处理出区间 ...
- 2Ants(独立,一个个判,弹性碰撞,想象)
AntsDescriptionAn army of ants walk on a horizontal pole of length l cm, each with a constant speed ...
- Problem C: 计算机类
Description 定义一个Computer类,有两个属性: 1. 字符串属性name,用于表示计算机的名字. 2. 静态整型属性cnt,用于记录产生的计算机对象的个数. 至少有如下成员函数: 1 ...
- vue学习(九) 使用内联样式设置style样式
/html <div id="app"> //对象就是无序键值对的集合 <h1 :style="{ color:red, 'font-weight':2 ...
- 数字麦克风PDM信号采集与STM32 I2S接口应用(四)--单片机源码
本文是数字麦克风笔记文章的单片机程序.一些朋友私信我,调试出问题. 我就把源码贴出来吧,可能主要问题是DMA的配置. 尤其双DMA时候,需要手动启动I2S的接收DMA,HAL库没有这个接口,不看dat ...
- ~~并发编程(十四):Queue~~
进击のpython ***** 并发编程--Queue 进程其实就提过这个Queue的问题,我们为什么在进程使用Queue? 是因为当时我们想要对共享数据进行修改,同时也希望它能够自动的给我加个锁 基 ...
- java实现链表反转
为什么面试常考链表反转 链表是常用的数据结构,同时也是面试常考点,链表为什么常考,因为链表手写时,大多都会有许多坑,比如在添加节点时因为顺序不对的话会让引用指向自己,因此会导致内存泄漏等问题,Java ...
- 800页的《数据随想录》PDF版电子书|百度网盘免费下载|数据科学领域必读
百度网盘免费下载|<数据随想录> 提取码:51y7 本电子书内容包含从数据埋点到数据可视化整个链条的内容,同时,也整理了很多小伙伴们在交流社区中常问到的问题<数据百问>系列 数 ...