有没有办法在 Linux 中获得块设备的缓存命中率/未命中率?

Kyl*_*ndt 20 linux cache io

是否可以在 Linux 中看到有多少来自用户空间的读写请求最终导致块设备的缓存命中和未命中?

小智 9

您可以开发自己的SystemTap脚本。您需要考虑以下两个子系统:

  • VFS:这代表缓冲区缓存之前的所有 I/O 请求(即绝对每个 I/O 请求);查看“vfs.read”、“vfs.write”和“kernel.function(“vfs_*”)”探测器;您需要通过它们各自的主要+次要编号过滤掉要监视的块设备。
  • 块:这表示在 I/O 调度程序之前发送到块设备的所有 I/O 请求(它也对 I/O 请求进行合并 + 重新排序);在这里我们知道 Buffer 缓存错过了哪些请求;查看“ioblock.request”探测。

SystemTap 开发需要一些时间来学习。如果你是一个中等开发者并且对 Linux 有很好的了解,你应该在 3-4 天内完成。是的,学习需要时间,但您会对结果感到非常满意 - SystemTap 使您有机会(安全地)在 Linux 内核的几乎任何位置放置探测器。

请注意,您的内核必须支持加载和卸载内核模块。现在大多数股票内核都支持这一点。您还需要为您的内核安装调试符号。对于我的 Ubuntu 系统,这就像下载 Ubuntu 内核开发团队为我编译的几百 MB .deb 文件一样简单。例如,这在SystemtapOnUbuntu Wiki 页面中有解释。

PS 仅当您没有其他解决方案时才采用 SystemTap 方法,因为它是一个您必须学习的全新框架,并且需要花费时间/金钱,有时还会遇到挫折。


小智 8

我继续为此编写了一个 stap 脚本。systemtap wiki 上有一个,但似乎不正确。在基本测试中,这看起来非常准确,但 YMMV。

#! /usr/bin/env stap
global total_bytes, disk_bytes, counter

probe vfs.read.return {
  if (bytes_read>0) {
    if (devname=="N/A") {
    } else {
      total_bytes += bytes_read
    }
  }
}
probe ioblock.request
{
    if (rw == 0 && size > 0)
    {
        if (devname=="N/A") { 
        } else {
          disk_bytes += size
        }
    }

}

# print VFS hits and misses every 5 second, plus the hit rate in %
probe timer.s(5) {
    if (counter%15 == 0) {
        printf ("\n%18s %18s %10s %10s\n", 
            "Cache Reads (KB)", "Disk Reads (KB)", "Miss Rate", "Hit Rate")
    }
    cache_bytes = total_bytes - disk_bytes
    if (cache_bytes < 0)
      cache_bytes = 0
    counter++
    hitrate =  10000 * cache_bytes / (cache_bytes+disk_bytes)
    missrate = 10000 * disk_bytes / (cache_bytes+disk_bytes)
    printf ("%18d %18d %6d.%02d%% %6d.%02d%%\n",
        cache_bytes/1024, disk_bytes/1024,
        missrate/100, missrate%100, hitrate/100, hitrate%100)
    total_bytes = 0
    disk_bytes = 0
}
Run Code Online (Sandbox Code Playgroud)