web-dev-qa-db-ja.com

Linuxでブロックデバイスのキャッシュヒット/ミス率を取得する方法はありますか?

Linuxでユーザースペースからの読み取りおよび書き込み要求がブロックデバイスでキャッシュヒットとキャッシュミスを引き起こした結果をいくつ見ることができますか?

20
Kyle Brandt

独自の SystemTap スクリプトを開発できます。次の2つのサブシステムを考慮する必要があります。

  • 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カーネル開発チームが私のためにコンパイルしました。これは、たとえば SystemtapOnUbunt Wikiページで説明されています。

追伸SystemTapのアプローチは、他に解決策がない場合にのみ行ってください。これは、学ぶ必要のあるまったく新しいフレームワークであり、時間とお金がかかり、フラストレーションがかかる場合があるためです。

9
famzah

私は先に進んで、このためのstapスクリプトを作成しました。 systemtap wikiに1つありますが、正しくないようです。基本的なテストでは、これはかなり正確に見えますが、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
}
8
Dave Wright

/ proc/slabinfoは良い出発点ですが、探している情報があまり得られません(複数のコアと統計が有効になっているシステムでのヒット/ミスのパーセンテージに惑わされないでください。これらは別のものです)。私が知る限り、カーネルからその特定の情報を引き出す方法はありませんが、実行するコードを書くことはそれほど難しくありません。

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

2
BMDan

perf-tools パッケージの cachestat ユーティリティがあります。

著者はまた、人々が使用するいくつかの(おそらくより粗い)代替案をリストします:

A)iostat(1)を使用してページのキャッシュミス率を調査し、ディスクの読み取りを監視します。これらは、キャッシュミスであり、O_DIRECTなどではないと想定してください。ミスはアプリケーションの痛みに比例するため、ミス率は通常、比率よりも重要なメトリックです。また、キャッシュサイズを確認するにはfree(1)を使用してください。

B)ページキャッシュを削除し(echo 1>/proc/sys/vm/drop_caches)、パフォーマンスの低下を測定します!私はネガティブな実験の使用が好きですが、これはもちろん、キャッシュの使用にいくつかの光を当てる痛みを伴う方法です。

C)sar(1)を使用して、マイナーおよびメジャーの障害を調査します。私はこれがうまくいくとは思いません(例えば、通常のI/O)。

D)cache-hit-rate.stp SystemTapスクリプトを使用します。これは、Linuxページキャッシュヒット率のインターネット検索で2番目です。スタック、VFSインターフェイスの上位のキャッシュアクセスを計測するため、ファイルシステムやストレージデバイスへの読み取りを確認できます。キャッシュミスは、ディスクI/Oを介して測定されます。これは、一部のワークロードタイプ(そのページの「レッスン」で言及されているタイプ)も見逃しており、比率を「レート」と呼んでいます。

2
lemonsqueeze

特定のプロセスのIOヒット/ミス率に興味がある場合は、シンプルですが非常に効果的なアプローチは/proc/<pid>/ioファイル。

ここには4つのキー値があります。

  • rcharアプリケーションの観点からの読み取りバイトの総数(つまり:違いなし)キャッシュからではなく、物理ストレージから満たされた読み取りの間で行われます)
  • wchar:上記と同じですが、書き込まれたバイトについて
  • read_bytes:ストレージサブシステムから読み取ったバイトreally
  • write_bytes:ストレージサブシステムに書き込まれたバイトreally

プロセスに次の値があるとします。

rchar: 1000000
read_bytes: 200000

読み取りキャッシュミス率(バイト単位)は100*200000/1000000 = 20%、ヒット率は100-20 = 80%

ただし、注意点があります。rchar値にはtty IOとしてのものが含まれるため、パイプに対して大量の読み取り/書き込みを行うプロセスの場合、上記の計算は歪曲され、有効なヒット率よりも高いヒット率が報告されます。

1
shodanshok