web-dev-qa-db-ja.com

Linuxメモリの断片化

Linuxでメモリの断片化を検出する方法はありますか?これは、長時間実行されている一部のサーバーでパフォーマンスの低下に気づき、プロセスを再起動した後にのみ、パフォーマンスが向上するためです。 Linuxのヒュージページサポートを使用すると、より多くのことに気づきました。Linuxのヒュージページは断片化する傾向がありますか?

特に/ proc/buddyinfoを見てきました。それを調べるためのより良い方法があるかどうかを知りたいです(CLIコマンド自体だけでなく、プログラムや理論的なバックグラウンドで行うでしょう)。

20
Raghu

linux タグに答えています。私の答えはLinuxにのみ固有です。

はい、巨大なページは断片化する傾向があります。メモリには2つのビューがあります。1つはプロセスが取得するもの(仮想)で、もう1つはカーネルが管理するもの(実数)です。ページが大きくなるほど、特にサービスがデフォルトで割り当てられており、それらよりも多くのメモリに書き込む他のシステムをサポートする必要があるシステムでサービスが実行されている場合、そのネイバーをグループ化(および保持)することが難しくなります。実際に使用してしまいます。

(実際の)許可されたアドレスのカーネルのマッピングはプライベートです。カーネルがユーザースペースを混乱させることなくオーバーコミットできる必要があるため、カーネルがそれらを提示するときにユーザースペースがそれらを見るのには非常に良い理由があります。プロセスは、カーネルが実際に何であるかを意識せずに、機能する適切な連続した "Disneyfied"アドレス空間を取得しますdoingその記憶を舞台裏で。

長時間実行されているサーバーでパフォーマンスの低下が見られる理由は、割り当てられたブロックが明示的にロックされていないためです(例:mlock()/mlockall()またはposix_madvise())。しばらく変更されましたページアウトされました、つまり、サービスはディスクを読み取らなければならないときに、ディスクにスキップします。この動作を変更すると、プロセスがbad neighborになるため、多くの人がRDBMSをweb/php/python/Ruby /とはまったく異なるサーバーに配置しますなんでも。それを正直に解決する唯一の方法は、隣接するブロックの競合を減らすことです。

断片化は、ページAがメモリ内にあり、ページBがスワップに移動した場合にのみ(ほとんどの場合)本当に顕著です。当然のことながら、サービスを再起動するとこれが「解決」したように見えますが、カーネルがまだオーバーコミット率の範囲内で(現在)新しく割り当てられたブロックをページアウトする機会をまだ持っていないためです。

実際、高負荷で「Apache」を再起動すると、他のサービスが所有しているブロックがディスクに直接送信されます。したがって、はい、「Apache」は短期間で改善しますが、「mysql」は、少なくとも、十分な物理メモリが不足している場合に、カーネルがそれらを同じように苦しめるまで苦しむ可能性があります。

より多くのメモリを追加するか、要求の多いmalloc()コンシューマを分割します。

vmstatを試して、実際にどこに保存されているかを確認してください。

12
Tim Post

大きなページを使用しても、Linuxで余分なメモリが断片化することはありません。 Linuxによる巨大ページのサポートは、共有メモリ(shmgetまたはmmapを使用)のみを対象としています。使用される巨大ページは、システム管理者が特別にリクエストして事前に割り当てる必要があります。いったんメモリに入ると、それらはそこに固定され、スワップアウトされません。メモリの断片化に直面して巨大ページをスワップするという課題は、それらがメモリに固定されたままである理由です(2MBの巨大ページを割り当てるとき、カーネルは512の連続する空き4KBページを見つける必要があり、存在しない場合もあります)。

巨大ページに関するLinuxのドキュメント: http://lwn.net/Articles/375098/

メモリの断片化により、巨大なページの割り当てが遅くなる可能性がある1つの状況があります(ただし、巨大なページが原因のメモリの断片化は発生しません)。それは、システムがアプリケーションから要求された場合、巨大なページのプールを拡大するように構成されています。/proc/sys/vm/nr_overcommit_hugepagesが/ proc/sys/vm/nr_hugepagesより大きい場合、これが発生する可能性があります。

4
jstultz

有る /proc/buddyinfo非常に便利です。 Pythonスクリプトで実行できるように、Nice出力形式を使用するとより便利です。

https://Gist.github.com/labeneator/9574294

巨大なページの場合、2097152(2MiB)サイズ以上のフリーフラグメントが必要です。透過的な巨大なページの場合、カーネルが要求されたときに自動的に圧縮されますが、取得できる数を確認する場合は、rootとして実行します。

echo 1 | Sudo tee /proc/sys/vm/compact_memory

また、はい、巨大なページは断片化に大きな問題を引き起こします。巨大なページを取得できないか、ページが存在するために、カーネルはページを取得するために多くの時間を費やします。

私のために働く解決策があります。いくつかのサーバーとラップトップで使用しています。仮想マシンに最適です。

kernelcore=4G Linuxカーネルコマンドラインのオプション。私のサーバーでは8Gを使用しています。カーネルがそのメモリの外に何かを割り当てるのを防ぐので、数に注意してください。大量のソケットバッファーを必要とするサーバーや、ディスク書き込みを数百のドライブにストリーミングするサーバーは、このように制限されることを好みません。スラブまたはDMAに「固定」する必要があるメモリ割り当てはすべてこのカテゴリに含まれます。

その後、他のすべてのメモリが「移動可能」になります。つまり、巨大なページ割り当てのためにニースチャンクに圧縮できます。これで、透明な巨大ページが実際に機能し、想定どおりに機能するようになります。カーネルがさらに2Mページを必要とするときはいつでも、それは単に4Kページを別の場所に再マップすることができます。

そして、これがゼロコピー直接IOとどのように相互作用するかは完全にはわかりません。 「可動ゾーン」内のメモリは固定されるとは想定されていませんが、直接IOリクエストはDMAの場合とまったく同じです。コピーする可能性があります。可動ゾーンに固定される可能性があります。どちらの場合でも、それはおそらくあなたが望んでいたものとは正確には異なります。

0
Zan Lynx