web-dev-qa-db-ja.com

RAMの30%は「バッファ」です。それは何ですか?

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           501M        146M         19M        9.7M        335M        331M
Swap:          1.0G         85M        938M

$ free -w -h
              total        used        free      shared     buffers       cache   available
Mem:           501M        146M         19M        9.7M        155M        180M        331M
Swap:          1.0G         85M        938M

freeの出力で「バッファ」を説明または説明するにはどうすればよいですか?

このシステムには(既知の)問題はありません。 「バッファ」が「キャッシュ」(155M対180M)とほぼ同じ高さであることを知って驚いたり、興味を引いたりしました。 「キャッシュ」はファイルコンテンツのページキャッシュを表し、「キャッシュ/バッファ」の最も重要な部分である傾向があると思いました。 「バッファ」が何のためにあるのか私はあまりわかりません。

たとえば、これをRAMの多いラップトップと比較しました。私のラップトップでは、「バッファ」の数値は「キャッシュ」(200M対4G)よりも桁違いに小さくなっています。 「バッファー」とは何かについて適切に理解していれば、小規模なシステムでバッファーがこれほど大きな割合で増加する理由を尋ねることができます。

man proc(私は陽気に古くなった「大」の定義を無視します):

バッファ%lu

非常に大きくならないはずのrawディスクブロック用の比較的一時的なストレージ(20MB程度)。

キャッシュされた%lu

ディスクから読み込まれたファイルのメモリ内キャッシュ(ページキャッシュ)。 SwapCachedは含まれません。


$ free -V
free from procps-ng 3.3.12
$ uname -r
4.9.0-6-marvell
$ systemd-detect-virt
none

$ cat /proc/meminfo
MemTotal:         513976 kB
MemFree:           20100 kB
MemAvailable:     339304 kB
Buffers:          159220 kB
Cached:           155536 kB
SwapCached:         2420 kB
Active:           215044 kB
Inactive:         216760 kB
Active(anon):      56556 kB
Inactive(anon):    73280 kB
Active(file):     158488 kB
Inactive(file):   143480 kB
Unevictable:       10760 kB
Mlocked:           10760 kB
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         513976 kB
LowFree:           20100 kB
SwapTotal:       1048572 kB
SwapFree:         960532 kB
Dirty:               240 kB
Writeback:             0 kB
AnonPages:        126912 kB
Mapped:            40312 kB
Shmem:              9916 kB
Slab:              37580 kB
SReclaimable:      29036 kB
SUnreclaim:         8544 kB
KernelStack:        1472 kB
PageTables:         3108 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1305560 kB
Committed_AS:    1155244 kB
VmallocTotal:     507904 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

$ Sudo slabtop --once
 Active / Total Objects (% used)    : 186139 / 212611 (87.5%)
 Active / Total Slabs (% used)      : 9115 / 9115 (100.0%)
 Active / Total Caches (% used)     : 66 / 92 (71.7%)
 Active / Total Size (% used)       : 31838.34K / 35031.49K (90.9%)
 Minimum / Average / Maximum Object : 0.02K / 0.16K / 4096.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 59968  57222   0%    0.06K    937       64      3748K buffer_head            
 29010  21923   0%    0.13K    967       30      3868K dentry                 
 24306  23842   0%    0.58K   4051        6     16204K ext4_inode_cache       
 22072  20576   0%    0.03K    178      124       712K kmalloc-32             
 10290   9756   0%    0.09K    245       42       980K kmalloc-96             
  9152   4582   0%    0.06K    143       64       572K kmalloc-node           
  9027   8914   0%    0.08K    177       51       708K kernfs_node_cache      
  7007   3830   0%    0.30K    539       13      2156K radix_tree_node        
  5952   4466   0%    0.03K     48      124       192K jbd2_revoke_record_s   
  5889   5870   0%    0.30K    453       13      1812K inode_cache            
  5705   4479   0%    0.02K     35      163       140K file_lock_ctx          
  3844   3464   0%    0.03K     31      124       124K anon_vma               
  3280   3032   0%    0.25K    205       16       820K kmalloc-256            
  2730   2720   0%    0.10K     70       39       280K btrfs_trans_handle     
  2025   1749   0%    0.16K     81       25       324K filp                   
  1952   1844   0%    0.12K     61       32       244K kmalloc-128            
  1826    532   0%    0.05K     22       83        88K trace_event_file       
  1392   1384   0%    0.33K    116       12       464K proc_inode_cache       
  1067   1050   0%    0.34K     97       11       388K shmem_inode_cache      
   987    768   0%    0.19K     47       21       188K kmalloc-192            
   848    757   0%    0.50K    106        8       424K kmalloc-512            
   450    448   0%    0.38K     45       10       180K ubifs_inode_slab       
   297    200   0%    0.04K      3       99        12K eventpoll_pwq          
   288    288 100%    1.00K     72        4       288K kmalloc-1024           
   288    288 100%    0.22K     16       18        64K mnt_cache              
   287    283   0%    1.05K     41        7       328K idr_layer_cache        
   240      8   0%    0.02K      1      240         4K fscrypt_info           
13
sourcejedi
  1. 「バッファ」と他のキャッシュの違いは何ですか?
  2. なぜこの違いがそれほど目立つのですか? (考えられる歴史的理由)
  3. Buffersは何に使用されますか?
  4. 特にBuffersが特に大きいか小さいと予想されるのはなぜですか?

1.「バッファ」と他のタイプのキャッシュの違いは何ですか?

Buffersは、ブロックデバイスに使用されるページキャッシュの量を報告します。カーネルは、Cachedを報告するときに、意図的にこの量を残りのページキャッシュから差し引く必要があります。

meminfo_proc_show() を参照してください:

_cached = global_node_page_state(NR_FILE_PAGES) -
         total_swapcache_pages() - i.bufferram;
...

show_val_kb(m, "MemTotal:       ", i.totalram);
show_val_kb(m, "MemFree:        ", i.freeram);
show_val_kb(m, "MemAvailable:   ", available);
show_val_kb(m, "Buffers:        ", i.bufferram);
show_val_kb(m, "Cached:         ", cached);
_

2.なぜこの区別が目立つのですか? (考えられる歴史的理由)

ページキャッシュはMMUページサイズ、通常は最小4096バイト)の単位で機能します。これはmmap()、つまりメモリマップファイルアクセスに不可欠です。[1] [2]独立したプロセス間でロードされたプログラム/ライブラリコードのページを共有し、個別のページをオンデマンドでロードできるようにします(他にスペースが必要で、最近使用されていないページのアンロードにも使用できます)。

[1] メモリマップI/O -GNU Cライブラリマニュアル。
[2] mmap -ウィキペディア。

初期のUNIXにはディスクブロックの「バッファキャッシュ」があり、mmap()はありませんでした。どうやらmmap()が最初に追加されたとき、彼らは単にページキャッシュをバッファキャッシュの上にボルトで固定しました。これは、聞こえるほど厄介です。最終的に、UNIXベースのOSはバッファキャッシュを取り除きました。したがって、すべてのファイルキャッシュはページ単位になります。ページは、ディスク上の場所ではなく、(ファイル、オフセット)によって検索されます。これは「統一バッファキャッシュ」と呼ばれていましたが、これはおそらく「バッファキャッシュ」に慣れ親しんでいたためです。[3]

[3] UBC:NetBSD用の効率的な統合I/Oおよびメモリキャッシングサブシステム

「Linuxが追加する興味深いひねりの1つは、ページがディスクに格納されているデバイスブロック番号が、_buffer_head_構造体のリストの形式でページとともにキャッシュされることです。変更されたページがディスクに書き戻される場合、I/O要求をすぐにデバイスドライバーに送信できます。間接ブロックを読み取ってページのデータを書き込む場所を決定する必要はありません。」[3]

Linux 2.2では、書き込みには使用されるが読み取りには使用されない個別の「バッファキャッシュ」がありました。 「ページキャッシュは、データを書き戻すためにバッファキャッシュを使用し、データの追加のコピーが必要であり、一部の書き込み負荷に対してメモリ要件を2倍にしました」(?)。[4]詳細についてはあまり気にしないでください。しかし、この歴史がLinuxがBuffersの使用状況を個別に報告する理由の1つになるでしょう。

[4] Linux 2.4のメモリ管理におけるページの置き換え 、Rik van Riel。

対照的に、Linux 2.4以降では、追加のコピーは存在しません。 「システムはディスクIOページキャッシュページと直接やり取りします。] [4] Linux 2.4は2001年にリリースされました。

3. Buffersは何に使用されますか?

ブロックデバイスはファイルとして扱われるため、ページキャッシュがあります。これは「ファイルシステムメタデータとrawブロックデバイスのキャッシュ」に使用されます。[4]しかし、Linuxの現在のバージョンでは、ファイルシステムはファイルの内容をコピーしないため、「二重キャッシュ」はありません。

ページキャッシュのBuffersの部分はLinuxバッファキャッシュであると思います。一部のソースはこの用語に同意しない場合があります。

ファイルシステムが使用するバッファキャッシュの量は、特定のファイルシステムの詳細によって異なります。問題のシステムはext4を使用しています。 ext3/ext4は、ジャーナル、ディレクトリコンテンツ、その他のメタデータにLinuxバッファキャッシュを使用します。

Ext3、ext4、ocfs2などの特定のファイルシステムは、jbdまたはjbd2レイヤーを使用して物理ブロックジャーナリングを処理し、このレイヤーは基本的にバッファーキャッシュを使用します。

- メール記事 by Ted Tso 、2013

Linuxカーネルバージョン2.4以前は、Linuxには個別のページキャッシュとバッファキャッシュがありました。 2.4以降、ページキャッシュとバッファキャッシュは統合され、Buffersは、ページキャッシュに表示されない生のディスクブロックです。つまり、ファイルデータではありません。

...

ただし、カーネルはページではなくブロックの観点からブロックI/Oを実行する必要があるため、バッファキャッシュは残ります。ほとんどのブロックはファイルデータを表すため、ほとんどのバッファキャッシュはページキャッシュによって表されます。ただし、少量のブロックデータ(メタデータやrawブロックI/Oなど)はファイルでバックアップされないため、バッファーキャッシュのみで表されます。

- Quoraのペアの回答 by Robert Love 、最終更新2013。

どちらのライターも、Linuxカーネルメモリ管理に携わってきたLinux開発者です。最初のソースは、技術的な詳細についてより具体的です。 2番目の情報源は、より一般的な要約であり、一部の仕様では矛盾している可能性があります。

キャッシュがページ内で索引付けされている場合でも、ファイルシステムが部分的なページのメタデータ書き込みを実行する可能性があることは事実です。ユーザープロセスでも、write()を使用すると、少なくともブロックデバイスに対して(mmap()とは対照的に)、部分ページ書き込みを実行できます。これは書き込みにのみ適用され、読み取りには適用されません。ページキャッシュを読み取る場合、ページキャッシュは常にページ全体を読み取ります。

Linusは、ブロックサイズの書き込みを行うためにバッファキャッシュが必要ないこと、およびファイルシステムがページキャッシュを独自にアタッチしていても部分的なページメタデータの書き込みを実行できることを好む ブロックデバイスの代わりにファイル。私は彼がext2がこれをしていると言うのは正しいと確信しています。ジャーナリングシステムを備えたext3/ext4はサポートしていません。この設計につながった問題が何であるかはあまり明確ではありません。彼が怒っていた人々は説明するのに飽きた。

ext4_readdir()は、Linusの発言を満たすために変更されていません。彼の望ましいアプローチが他のファイルシステムのreaddir()で使用されているのもわかりません。 XFSはディレクトリにもバッファキャッシュを使用すると思います。 bcachefsはreaddir()のページキャッシュをまったく使用しません。 btreeには独自のキャッシュを使用します。 btrfsで何かが欠けている可能性があります。

4.特にBuffersが特に大きくなる、または小さくなることが予想されるのはなぜですか?

この場合、ファイルシステムの ext4ジャーナルサイズ は128Mです。これが、1)バッファキャッシュが128Mをわずかに超えて安定する理由を説明しています。 2)バッファキャッシュは、ラップトップのRAM)の量に比例してスケーリングしません。

その他の考えられる原因については、 を参照してください。freeからの出力のbuffers列とは何ですか?freeによって報告される「バッファ」は、実際にはBuffersと再利用可能なスラブメモリの組み合わせです。


ジャーナルの書き込みがバッファーキャッシュを使用していることを確認するために、ニースでファイルシステムを高速にシミュレートしましたRAM(tmpfs))、さまざまなジャーナルサイズの最大バッファー使用量を比較しました。

_# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=256
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size:             256M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2521        4321         285          66         947        5105
Swap:          7995           0        7995

# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2523        3872         551         237        1223        4835
Swap:          7995           0        7995
_

_# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=16
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size:             16M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2507        4337         285          66         943        5118
Swap:          7995           0        7995

# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2509        4290         315          77         977        5086
Swap:          7995           0        7995
_

この回答の履歴:ジャーナルを見るようになった経緯

私は最初にTed Tsoの電子メールを見つけ、それがwriteキャッシングを強調していることに興味をそそられました。 「ダーティ」、未書き込みデータが私のシステムでRAMの30%に到達できた場合、それは驚くべきことでしょう。 。_Sudo atop_は、問題のシステムが10秒の間隔で一貫して1MBのみを書き込むことを示しています。関係するファイルシステムは、このレートの100倍以上に対応できます(USB2ハードディスクドライブ上にあり、最大スループット〜20MB /秒)。

Blktrace(_btrace -w 10 /dev/sda_)を使用すると、読み取られるデータがほとんどないため、キャッシュされているIOは書き込みである必要があります。また、mysqldは、IOを実行する唯一のuserspaceプロセスです。

書き込みを担当しているサービス(icinga2がmysqlに書き込む)を停止し、再確認しました。 「バッファ」が20M未満に下がるのを見ました-それについての説明はありません-そのままです。ライターを再起動すると、「バッファ」が10秒間隔で約0.1Mずつ上昇することが示されます。私はそれがこの速度を一貫して維持し、70M以上に上昇するのを観察しました。

_echo 3 | Sudo tee /proc/sys/vm/drop_caches_を実行すると、「バッファ」を再び4.5Mに下げるのに十分でした。これは、私のバッファの蓄積が「クリーンな」キャッシュであることを証明しています。Linuxは必要なときにすぐにドロップできます。このシステムは書き込まれていないデータを蓄積していません。 (_drop_caches_はライトバックを実行しないため、ダーティページを削除できません。最初にキャッシュをクリーンアップするテストを実行する場合は、syncコマンドを使用します)。

Mysqlディレクトリ全体はわずか150Mです。蓄積するバッファはmysqlの書き込みからのメタデータブロックを表す必要がありますが、このデータには非常に多くのメタデータブロックがあると思うと驚きました。

14
sourcejedi

あなたのバージョンのfreeは正しい考えを持っています。デフォルトでは、レポートにバッファとキャッシュを組み合わせます。これは基本的に同じものだからです。これらは両方とも、RAM(その二次記憶装置:ディスクとSSDがより高速))で記憶しているコンピューターであり、ディスクとSSDを読み取ったときにすでに見たことです。

オペレーティングシステムがメモリが他の何かによってよりよく使用されていると感じた場合は、メモリを解放できます。したがって、バッファとキャッシュについて心配する必要はありません。

ただし、DVDを鑑賞すると、バッファが上がり、他のバッファ/キャッシュコンテンツを追い出す可能性があります。したがって、nocacheを使用してDVDプレーヤーを実行することができます(それが問題の原因である場合)。

3
ctrl-alt-delor