HugePages の長所ず短所

HugePages の長所ず短所

コヌス受講生向けに甚意された蚘事の翻蚳 「Linux管理者」.

以前、Linux で Hugepages をテストしお有効にする方法に぀いお説明したした。
この蚘事は、実際に Hugepages を䜿甚する堎所がある堎合にのみ圹立ちたす。 私は、Hugepages が魔法のように生産性を向䞊させるずいう芋通しに隙される倚くの人に䌚いたした。 ただし、ヒュヌゞペヌゞングは​​耇雑なトピックであり、䜿甚方法を誀るずパフォヌマンスが䜎䞋する可胜性がありたす。

パヌト 1: Linux で hugepage が有効になっおいるこずを確認する (オリゞナル) ここで)

問題
システムで HugePages が有効になっおいるかどうかを確認する必芁がありたす。

解決策
それは非垞に簡単です:

cat /sys/kernel/mm/transparent_hugepage/enabled

次のようなものが埗られたす。

always [madvise] never

利甚可胜なオプションのリストが衚瀺されたす (い぀も、マッドノィス、決しお)、珟圚アクティブなオプションは括匧で囲たれたす (デフォルトでは マバむス).

マバむス ずいう意味です transparent hugepages を䜿甚しお明瀺的に hugepage を芁求するメモリ領域に察しおのみ有効になりたす。 マッドバむス(2).

垞に ずいう意味です transparent hugepages すべおのプロセスに察しお垞に有効になりたす。 これにより通垞はパフォヌマンスが向䞊したすが、倚くのプロセスが少量のメモリを消費するナヌスケヌスでは、党䜓のメモリ負荷が倧幅に増加する可胜性がありたす。

決しお ずいう意味です transparent hugepages Madvise を䜿甚しおリク゚ストされた堎合でも含たれたせん。 詳现に぀いおは、お問い合わせください ドキュメンテヌション Linux カヌネル。

デフォルト倀を倉曎する方法

オプション1盎接倉曎 sysfs (再起動埌、パラメヌタはデフォルト倀に戻りたす):

echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabled

オプション2: 倉曎された構成でカヌネルを再コンパむルしお、システムのデフォルトを倉曎したす (このオプションは、カスタム カヌネルを䜿甚しおいる堎合にのみ掚奚されたす)。

  • 垞にデフォルトで蚭定するには、次を䜿甚したす。
    CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
  • Madvise をデフォルトずしお蚭定するには、次を䜿甚したす。
    CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
    # Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y

パヌト 2: HugePages の長所ず短所

Hugepages を䜿甚する際の利点、欠点、および考えられる萜ずし穎を遞択的に説明しおいきたす。 技術的に耇雑で衒孊的な蚘事は、Hugepages が䞇胜薬だず思い蟌んでいる人々にずっおは理解するのが難しいず思われるため、簡朔にするために正確さを犠牲にしたす。 倚くのトピックは非垞に耇雑であるため、倧幅に簡略化されおいるこずに留意しおください。

ここでは、Linux を実行しおいる 64 ビット x86 システムに぀いお話しおいるこず、および最近のほずんどすべおの Linux の堎合ず同様に、システムが透過的なヒュヌゞペヌゞをサポヌトしおいるず単玔に仮定しおいるこずに泚意しおください (ヒュヌゞペヌゞが䞊曞きされないこずは欠点ではないため)。環境。

以䞋のリンクにさらに技術的な説明を添付したす。

仮想メモリ

C++ プログラマであれば、メモリ内のオブゞェクトには特定のアドレス (ポむンタ倀) があるこずをご存知でしょう。

ただし、これらのアドレスは必ずしもメモリ内の物理アドレス (RAM アドレス) を反映しおいるわけではありたせん。 これらは仮想メモリ内のアドレスを衚したす。 プロセッサには、カヌネルが仮想メモリを物理的な堎所にマップするのに圹立぀特別な MMU (メモリ管理ナニット) モゞュヌルがありたす。

このアプロヌチには倚くの利点がありたすが、最も重芁なものは次のずおりです。

  • パフォヌマンス (さたざたな理由による)。
  • プログラムの分離。぀たり、どのプログラムも別のプログラムのメモリから読み取るこずができたせん。

ペヌゞずは䜕ですか?

仮想メモリはペヌゞに分割されたす。 個々のペヌゞは特定の物理メモリを指したす。RAM 内の領域を指すこずも、ビデオ カヌドなどの物理デバむスに割り圓おられたアドレスを指すこずもできたす。

扱うペヌゞのほずんどは RAM をポむントしおいるか、スワップされおおり、ハヌド ドラむブたたは SSD に保存されおいたす。 カヌネルは各ペヌゞの物理レむアりトを管理したす。 スプヌフィングされたペヌゞにアクセスするず、カヌネルはメモリにアクセスしようずしおいるスレッドを停止し、ペヌゞをハヌド ドラむブ/SSD から RAM に読み取り、スレッドの実行を継続したす。

このプロセスはストリヌム透過的です。぀たり、必ずしも HDD/SSD から盎接読み取る必芁はありたせん。 通垞のペヌゞのサむズは 4096 バむトです。 Hugepages のサむズは 2 メガバむトです。

翻蚳関連バッファ (TLB)

プログラムがメモリのペヌゞにアクセスするずき、CPU はどの物理ペヌゞからデヌタを読み取るかを認識しおいる必芁がありたす (぀たり、仮想アドレス マップを持っおいる必芁がありたす)。

カヌネルには、䜿甚されおいるペヌゞに関するすべおの情報が含たれるデヌタ構造 (ペヌゞ テヌブル) がありたす。 このデヌタ構造を䜿甚するず、仮想アドレスを物理アドレスにマップできたす。

ただし、ペヌゞ テヌブルは非垞に耇雑で遅いため、プロセスがメモリにアクセスするたびにデヌタ構造党䜓を分析するこずはできたせん。

幞いなこずに、私たちのプロセッサには、仮想アドレスず物理アドレス間のマッピングをキャッシュする TLB がありたす。 ぀たり、最初のアクセス詊行ではペヌゞ テヌブルを解析する必芁がありたすが、その埌のペヌゞぞのアクセスはすべお TLB で凊理できるため、高速な操䜜が可胜になりたす。

物理デバむスずしお実装されおいるため (そもそも高速であるため)、その容量には制限がありたす。 したがっお、より倚くのペヌゞにアクセスしたい堎合、TLB はすべおのペヌゞのマッピングを保存できず、プログラムの実行が倧幅に遅くなりたす。

Hugepages が助けに来たす

では、TLB オヌバヌフロヌを回避するにはどうすればよいでしょうか? (プログラムには䟝然ずしお同じ量のメモリが必芁であるず想定しおいたす)。

ここでHugepagesが登堎したす。 4096 ぀の TLB ゚ントリだけを必芁ずする 2 バむトの代わりに、512 ぀の TLB ゚ントリがなんず XNUMX メガバむトを指すこずができるようになりたした。 TLB に XNUMX 個の゚ントリがあるず仮定したす。ここでは Hugepage なしで䞀臎させるこずができたす。

4096 b⋅512=2 MB

では、どうやっおそれらず比范できるのでしょうか。

2 MB⋅512=1 GB

これが、Hugepages が玠晎らしい理由です。 それほど劎力をかけずに生産性を向䞊させるこずができたす。 ただし、ここには重芁な泚意点がありたす。

Hugepage のスプヌフィング

カヌネルは、各メモリ ペヌゞの䜿甚頻床を自動的に監芖したす。 十分な物理メモリ (RAM) がない堎合、カヌネルは重芁床の䜎い (䜿甚頻床の䜎い) ペヌゞをハヌドディスクに移動しお、より重芁なペヌゞのために RAM を解攟したす。
原則ずしお、同じこずが Hugepage にも圓おはたりたす。 ただし、カヌネルが亀換できるのはペヌゞ党䜓のみであり、個々のバむトを亀換するこずはできたせん。

次のようなプログラムがあるずしたす。

char* mymemory = malloc(2*1024*1024); // ВПзьЌеЌ этП за ПЎМу Hugepage!
// ЗапПлМОЌ mymemory какОЌО-лОбП ЎаММыЌО
// СЎелаеЌ ЌМПгП ЎругОх вещей,
// кПтПрые прОвеЎут к пПЎЌеМе страМОцы mymemory
// ...
// ЗапрПсОЌ ЎПступ тПлькП к первПЌу байту
putchar(mymemory[0]); 

この堎合、カヌネルは、ナヌザヌが 2 バむトを読み取るために、ハヌド ドラむブ/SSD から 4096 メガバむトもの情報を眮き換える (読み取る) 必芁がありたす。 通垞のペヌゞの堎合、ハヌドドラむブ/SSD から読み取る必芁があるのは XNUMX バむトのみです。

したがっお、hugepage がオヌバヌラむドされた堎合、ペヌゞ党䜓にアクセスする必芁がある堎合にのみ読み取りが速くなりたす。 これは、メモリのさたざたな郚分にランダムにアクセスしようずしおいお、数キロバむトを読み取るだけの堎合は、通垞のペヌゞを䜿甚し、他には䜕も心配する必芁がないこずを意味したす。

䞀方、メモリの倧郚分に順次アクセスする必芁がある堎合は、hugepage を䜿甚するずパフォヌマンスが向䞊したす。 ただし、抜象的な゜フトりェアを䜿甚せずに自分でテストしお、䜕がより速く動䜜するかを確認する必芁がありたす。

メモリ内の割り圓お

C を䜜成する堎合は、次を䜿甚しおヒヌプから任意に小さい (たたはほが任意に倧きい) 量のメモリを芁求できるこずがわかりたす。 malloc()。 30 バむトのメモリが必芁だずしたす。

char* mymemory = malloc(30);

プログラマにずっおは、オペレヌティング システムに 30 バむトのメモリを「芁求」し、仮想メモリぞのポむンタを返しおいるように芋えるかもしれたせん。 でも実は malloc () 関数内から呌び出す単なる C 関数です brkずsbrk オペレヌティング システムにメモリを芁求たたは解攟したす。

ただし、割り圓おごずにさらに倚くのメモリを芁求するのは非効率です。 いく぀かのメモリセグメントがすでに解攟されおいる可胜性が最も高いです (free())、再利甚するこずができたす。 malloc() 解攟されたメモリを再利甚するための非垞に耇雑なアルゎリズムを実装したす。

同時に、すべおのこずはあなたにずっお気づかれずに起こっおいるので、なぜ心配する必芁があるでしょうか しかし、挑戊だからこそ、 free() そういう意味ではありたせん メモリは必然的に盎ちにオペレヌティング システムに返されたす。.

蚘憶の断片化ずいうものがありたす。 極端な堎合には、数バむトだけが䜿甚されおいるヒヌプ セグメントが存圚し、その間のすべおのバむトが解攟されるこずがありたす。 (free()).

メモリの断片化は非垞に耇雑なトピックであり、プログラムぞのわずかな倉曎でも重倧な圱響を䞎える可胜性があるこずに泚意しおください。 ほずんどの堎合、プログラムによっお重倧なメモリの断片化が匕き起こされるこずはありたせんが、ヒヌプの䞀郚の領域で断片化の問題が発生した堎合、hugepage によっお状況が悪化する可胜性があるこずに泚意する必芁がありたす。

hugepage の遞択的䜿甚

この蚘事を読んだ埌は、プログラムのどの郚分が hugepage を䜿甚するこずでメリットを埗られるのか、どの郚分がメリットを埗られないのかを刀断したこずになりたす。 それでは、そもそも hugepage を有効にする必芁があるのでしょうか?

幞いなこずに、䜿甚できたす madvise()ヒュヌゞペヌゞングが圹立぀メモリ領域に察しおのみヒュヌゞペヌゞングを有効にしたす。

たず、hugepages が madvise() モヌドで実行されおいるこずを確認したす。 説明曞 蚘事の冒頭に。

次に、䜿甚したす madvise()hugepage を䜿甚する堎所をカヌネルに正確に指瀺したす。

#include <sys/mman.h>
// АллПцОруйте бПльшПе кПлОчествП паЌятО, кПтПрую буЎете ОспПльзПвать
size_t size = 256*1024*1024;
char* mymemory = malloc(size);
// ПрПстП включОте hugepages

madvise(mymemory, size, MADV_HUGEPAGE);
// 
 О заЎайте слеЎующее
madvise(mymemory, size, MADV_HUGEPAGE | MADV_SEQUENTIAL)

このメ゜ッドは、メモリの管理方法に぀いおカヌネルにアドバむスするだけであるこずに泚意しおください。 これは、カヌネルが特定のメモリに察しお自動的に hugepage を䜿甚するずいう意味ではありたせん。

ドキュメントを参照しおください (マンペヌゞ)アドバむスメモリ管理に぀いお詳しく孊び、 madvise(), このトピックの孊習曲線は信じられないほど急です。 したがっお、本圓に䞊達したい堎合は、肯定的な結果が期埅できる前に、数週間読んでテストする準備をしおください。

䜕を読むべきですか

質問がありたす コメントに曞いおください

出所 habr.com

コメントを远加したす