有没有一种方法可以获取Linux中块设备的缓存命中率/未命中率?


Answers:


9

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

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

SystemTap开发需要一些时间来学习。如果您是中级开发人员并且对Linux有很好的了解,则应在3-4天之内完成。是的,它需要花费一些时间来学习,但是您会对结果感到非常满意-SystemTap使您有机会(安全地)将探针放置在Linux内核的几乎任何位置。

请注意,您的内核必须支持加载和卸载内核模块。如今,大多数库存内核都支持此功能。您还需要为内核安装调试符号。对于我的Ubuntu系统,这就像下载一个数百MB的.deb文件一样容易,Ubuntu内核开发团队为我编译了该文件。例如,在SystemtapOnUbuntu Wiki页面上对此进行了说明。

PS仅在没有其他解决方案的情况下才采用SystemTap方法,因为这是您必须学习的全新框架,并且需要花费时间/金钱,有时还要感到沮丧。


1
+1漂亮干净的说明。谢谢,我也将结帐systemtap。
risyasin

他们的Wiki中有一个SystemTap脚本
迈克尔·汉普顿

8

我继续为此编写了一个装订脚本。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
}

太棒了!我添加了一些平均缓存使用情况统计信息,以便在您将其关闭时将其打印出来:pastie.org/1845683
entropo 2011年

我已复制/粘贴您的代码来运行它,如果发生以下错误,semantic error: unable to find member 'bi_size' for struct bio (alternatives: bi_next bi_bdev bi_flags bi_rw bi_iter bi_phys_segments bi_seg_front_size bi_seg_back_size bi_remaining bi_end_io bi_private bi_ioc bi_css bi_integrity bi_vcnt bi_max_vecs bi_cnt bi_io_vec bi_pool bi_inline_vecs): operator '->' at /usr/share/systemtap/tapset/linux/ioblock.stp:113:20 source: size = $bio->bi_size ^ Pass 2: analysis failed. [man error::pass2]您能帮忙吗?
FopaLéonConstantin

2

/ proc / slabinfo是一个很好的开始,但是并不能完全为您提供所需的信息(不要被启用了多个内核和统计信息的系统的命中/未命中百分比所迷惑;这是其他一些东西)。据我所知,没有办法将特定信息从内核中提取出来,尽管编写一点代码来做并不是很困难。

编辑:http//www.kernel.org/doc/man-pages/online/pages/man5/slabinfo.5.html


1

现在有来自perf-tools软件包的cachestat实用程序。

作者还列出了人们使用的一些替代方案(可能更粗糙):

A)通过使用iostat(1)监视磁盘读取来研究页面高速缓存未命中率,并假设这些是高速缓存未命中,而不是O_DIRECT。无论如何,未命中率通常是比比率更重要的指标,因为未命中与应用程序痛苦成正比。也可以使用free(1)查看缓存大小。

B)删除页面缓存(回显1> / proc / sys / vm / drop_caches),并测量性能变差了多少!我喜欢使用否定实验,但这当然是了解缓存使用情况的一种痛苦方式。

C)使用sar(1)并研究次要和主要故障。我认为这不起作用(例如,常规I / O)。

D)使用cache-hit-rate.stp SystemTap脚本,该脚本在Internet搜索Linux页面缓存命中率中排名第二。它可以在VFS接口的堆栈中检测高速缓存访​​问,以便可以看到对任何文件系统或存储设备的读取。高速缓存未命中通过其磁盘I / O进行衡量。这也错过了一些工作负载类型(该页面的“课程”中提到了某些类型),并且呼叫比率是“费率”。


1

如果您对特定进程的IO命中率/未命中率感兴趣,则一种简单但非常有效的方法是读取/proc/<pid>/io文件。

在这里,您会发现4个关键值:

  • rchar:从应用程序角度来看的读取字节总数(即:从物理存储而不是从缓存满足的读取之间没有区别)
  • wchar:如上,但关于已写字节
  • read_bytes真正从存储子系统读取的字节
  • write_bytes实际写入存储子系统的字节

假设一个流程具有以下值:

rchar: 1000000
read_bytes: 200000

读取缓存未命中率(以字节为单位)为100*200000/1000000 = 20%,命中率为100-20 = 80%

但是,有一个陷阱:该rchar值包括作为tty IO的东西,因此对于从管道大量读取/向管道进行大量写入/写入的进程,上述计算将出现偏差,从而报告命中率高于有效值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.