Blog

cook:bcc

cachestat #

cachestat 以 1 秒的时间间隔,输出了 3 组缓存统计数据:

$ cachestat 1 3
   TOTAL   MISSES     HITS  DIRTIES   BUFFERS_MB  CACHED_MB
       2        0        2        1           17        279
       2        0        2        1           17        279
       2        0        2        1           17        279

cachestat 的输出其实是一个表格。每行代表一组数据,而每一列代表不同的缓存统计指标。这些指标从左到右依次表示:

  1. TOTAL ,表示总的 I/O 次数;
  2. MISSES ,表示缓存未命中的次数;
  3. HITS ,表示缓存命中的次数;
  4. DIRTIES, 表示新增到缓存中的脏页数;
  5. BUFFERS_MB 表示 Buffers 的大小,以 MB 为单位;
  6. CACHED_MB 表示 Cache 的大小,以 MB 为单位。

memleak #

$ /usr/share/bcc/tools/memleak -p $(pidof app) -a
Attaching to pid 12512, Ctrl+C to quit.
[03:00:41] Top 10 stacks with outstanding allocations:
    addr = 7f8f70863220 size = 8192
    addr = 7f8f70861210 size = 8192
    addr = 7f8f7085b1e0 size = 8192
    addr = 7f8f7085f200 size = 8192
    addr = 7f8f7085d1f0 size = 8192
    40960 bytes in 5 allocations from stack
        fibonacci+0x1f [app]
        child+0x4f [app]
        start_thread+0xdb [libpthread-2.27.so]

从 memleak 的输出观察应用是否在不停地分配内存,并且这些分配的地址没有被回收。若满足这种情况,说明有内存泄漏。

...

pidstat查看进程IO情况

Content #

idstat 加上 -d 参数,就可以看到进程的 I/O 情况,如下所示:

$ pidstat -d 1
13:39:51      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
13:39:52      102       916      0.00      4.00      0.00       0  rsyslogd

pidstat 的输出包括下面这些内容。

  1. 用户 ID(UID)和进程 ID(PID) 。

  2. 每秒读取的数据大小(kB_rd/s) ,单位是 KB。

  3. 每秒发出的写请求数据大小(kB_wr/s) ,单位是 KB。

  4. 每秒取消的写请求数据大小(kB_ccwr/s) ,单位是 KB。

  5. 块 I/O 延迟(iodelay),包括等待同步块 I/O 和换入块 I/O 结束的时间,单位是时钟周期。

Viewpoints #

From #

25 | 基础篇:Linux 磁盘I/O是怎么工作的(下)

iostat指标解读

Content #

iostat 是最常用的磁盘 I/O 性能观测工具,它提供了每个磁盘的使用率、IOPS、吞吐量等各种常见的性能指标,当然,这些指标实际上来自 /proc/diskstats。

iostat 提供了非常丰富的性能指标。 这些指标中,你要注意:

  1. %util ,就是磁盘 I/O 使用率;
  2. r/s+ w/s ,就是 IOPS;
  3. rkB/s+wkB/s ,就是吞吐量;
  4. r_await+w_await ,就是响应时间。

在观测指标时,也别忘了结合请求的大小( rareq-sz 和 wareq-sz)一起分析。

从 iostat 并不能直接得到磁盘饱和度。可以把平均请求队列长度或者读写请求完成的等待时间,跟基准测试的结果(比如通过 fio)进行对比,综合评估磁盘的饱和情况。

Viewpoints #

From #

25 | 基础篇:Linux 磁盘I/O是怎么工作的(下)

衡量磁盘性能的五个指标

Content #

说到磁盘性能的衡量标准,必须要提到五个常见指标:

  1. 使用率指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。使用率只考虑有没有 I/O,而不考虑 I/O 的大小。换句话说,当使用率是 100% 的时候,磁盘依然有可能接受新的 I/O 请求。

  2. 饱和度指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。

  3. IOPS(Input/Output Per Second)指每秒的 I/O 请求数。

  4. 吞吐量指每秒的 I/O 请求大小。

  5. 响应时间指 I/O 请求从发出到收到响应的间隔时间。

在数据库、大量小文件等这类随机读写比较多的场景中,IOPS 更能反映系统的整体性能;而在多媒体等顺序读写较多的场景中,吞吐量才更能反映系统的整体性能。

Viewpoints #

From #

25 | 基础篇:Linux 磁盘I/O是怎么工作的(下)

四种IO调度算法

Content #

Linux 内核支持四种 I/O 调度算法,分别是 NONE、NOOP、CFQ 以及 DeadLine。

  1. NONE 完全不使用任何 I/O 调度器,对文件系统和应用程序的 I/O 其实不做任何处理,常用在虚拟机中(此时磁盘 I/O 调度完全由物理机负责)。

  2. NOOP 最简单的 I/O 调度算法。它实际上是一个先入先出的队列,只做一些最基本的请求合并,常用于 SSD 磁盘。

  3. CFQ(Completely Fair Scheduler),也被称为完全公平调度器现在很多发行版的默认 I/O 调度器,它为每个进程维护了一个 I/O 调度队列,并按照时间片来均匀分布每个进程的 I/O 请求。

    类似于进程 CPU 调度,CFQ 还支持进程 I/O 的优先级调度,所以它适用于运行大量进程的系统,像是桌面环境、多媒体应用等。

  4. DeadLine 分别为读、写请求创建了不同的 I/O 队列,可以提高机械磁盘的吞吐量,并确保达到最终期限(deadline)的请求被优先处理。DeadLine 调度算法,多用在 I/O 压力比较重的场景,比如数据库等。

Viewpoints #

From #

24 | 基础篇:Linux 磁盘I/O是怎么工作的(上)

通用块层

Content #

Linux 通过一个统一的通用块层,来管理各种不同的块设备。

通用块层,其实是处在文件系统和磁盘驱动中间的一个块设备抽象层。它主要有两个功能 。

  1. 第一个功能跟虚拟文件系统的功能类似。向上,为文件系统和应用程序,提供访问块设备的标准接口;向下,把各种异构的磁盘设备抽象为统一的块设备,并提供统一框架来管理这些设备的驱动程序。

  2. 第二个功能,通用块层还会给文件系统和应用程序发来的 I/O 请求排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。

其中,对 I/O 请求排序的过程,也就是我们熟悉的 I/O 调度。事实上,Linux 内核支持四种 I/O 调度算法,分别是 NONE、NOOP、CFQ 以及 DeadLine。

Viewpoints #

From #

24 | 基础篇:Linux 磁盘I/O是怎么工作的(上)

同步IO与异步IO

Content #

根据是否等待响应结果,可以把文件 I/O 分为同步和异步 I/O:

  1. 同步 I/O 指应用程序执行 I/O 操作后,要一直等到整个 I/O 完成后,才能获得 I/O 响应。

    设置O_DSYNC或O_SYNC表示使用同步IO。 O_DSYNC表示要等文件数据写入磁盘后,才能返回;而 O_SYNC,则是在 O_DSYNC 基础上,要求文件元数据也要写入磁盘后,才能返回。

  2. 异步 I/O 指应用程序执行 I/O 操作后,不用等待完成和完成后的响应,而是继续执行就可以。等到这次 I/O 完成后,响应会用事件通知的方式,告诉应用程序。

    在访问管道或者网络套接字时,设置了 O_ASYNC 选项后,相应的 I/O 就是异步 I/O。这样,内核会再通过 SIGIO 或者 SIGPOLL,来通知进程文件是否可读写。

Viewpoints #

From #

23 | 基础篇:Linux 文件系统是怎么工作的?

阻塞IO与非阻塞IO

Content #

根据应用程序是否阻塞自身运行,可以把文件 I/O 分为阻塞 I/O 和非阻塞 I/O:

  1. 阻塞 I/O 指应用程序执行 I/O 操作后,如果没有获得响应,就会阻塞当前线程,自然就不能执行其他任务。

  2. 非阻塞 I/O 指应用程序执行 I/O 操作后,不会阻塞当前的线程,可以继续执行其他的任务,随后再通过轮询或者事件通知的形式,获取调用的结果。

比方说,访问管道或者网络套接字时,设置 O_NONBLOCK 标志,就表示用非阻塞方式访问;而如果不做任何设置,默认的就是阻塞访问。

Viewpoints #

From #

23 | 基础篇:Linux 文件系统是怎么工作的?

直接IO与非直接IO

Content #

根据是否利用操作系统的页缓存,可以把文件 I/O 分为直接 I/O 与非直接 I/O。

  1. 直接 I/O 指跳过操作系统的页缓存,直接跟文件系统交互来访问文件。

  2. 非直接 I/O 文件读写时,先要经过系统的页缓存,然后再由内核或额外的系统调用,真正写入磁盘。

想要实现直接 I/O,需要你在系统调用中,指定 O_DIRECT 标志。如果没有设置过,默认的是非直接 I/O。

不过要注意,直接 I/O、非直接 I/O,本质上还是和文件系统交互。如果是在数据库等场景中,你还会看到,跳过文件系统读写磁盘的情况,也就是我们通常所说的裸 I/O。

Viewpoints #

From #

23 | 基础篇:Linux 文件系统是怎么工作的?

缓冲IO与非缓冲IO

Content #

根据是否利用标准库缓存,可以把文件 I/O 分为缓冲 I/O 与非缓冲 I/O。

  1. 缓冲 I/O 指利用标准库缓存来加速文件的访问,而标准库内部再通过系统调度访问文件。

  2. 非缓冲 I/O 指直接通过系统调用来访问文件,不再经过标准库缓存。

这里所说的“缓冲”,是指标准库内部实现的缓存。比方说,你可能见到过,很多程序遇到换行时才真正输出,而换行前的内容,其实就是被标准库暂时缓存了起来。

无论缓冲 I/O 还是非缓冲 I/O,它们最终还是要经过系统调用来访问文件。而系统调用后,还会通过页缓存,来减少磁盘的 I/O 操作。

Viewpoints #

From #

23 | 基础篇:Linux 文件系统是怎么工作的?