ALLOC_FAIRフラグについて
概要
Linuxカーネルのメモリページ割り当てに関するメモ。
ALLOC_FAIR
というフラグについて説明する。
ページ割り当て処理
関数冒頭のコメントで This is the 'heart' of the zoned buddy allocator.
と書かれている通り、ページ割り当て処理の中心は関数 __alloc_pages_nodemask()
が担っている。
__alloc_pages_nodemask()
の処理はざっくり言うと以下の通りである。
- First allocation attempt
- 関数
get_page_from_freelist()
でページ割り当てを試みる。ALLOC_FAIR
が指定されるのはこちら(ここだけ)。
- 関数
- Slow path
- First allocation attemptで失敗した場合、関数
__alloc_pages_slowpath()
でページ割り当てを試みる。
- First allocation attemptで失敗した場合、関数
First allocation attempt
First allocation attemptの際に、割り当て条件として指定されるフラグの一つが、 ALLOC_FAIR
である。
First allocation attemptの処理をbreak downすると以下の通りである。
- ローカルノードでの割り当て試行
- zonelist(説明割愛)で指定されたzone(説明割愛)の内、呼び出し元CPUと同じNUMAノード(ローカルノード)に属するzoneからの割り当てを試行する。
- 全ノードでの割り当て試行
- zonelistで指定された全zoneについて、zonelistの登録順序で、再度割り当てを試行する。
このローカルノードでの割り当て試行を行う際、フラグ ALLOC_FAIR
が指定されていると、1つのzoneがlow watermarkに達するまで消費してから次のzoneへ進む「のではなく」、各zoneにおいて一定量 x
(= high_wmark_pages(zone) - low_wmark_pages(zone)
) で表される量を割り当てたら、もう次のzoneへ進む、というロジックで割り当て試行処理が行われる。
ローカルノードに属するzone群でのページ消費負担を フェア
に分散するロジックと理解できる。
他方、全ノードでの割り当て試行では、単純にzonelist順に一つのzoneがlow watermarkに達するまで消費して、次のzoneへ進む、というロジックとなる。
ちなみにローカルノードでの割り当て試行において、全てのzoneでの割当量が一旦 x
に達すると、各zoneでいくら割り当てたかのカウンタがリセットされ、再び各zoneにおいて x
までは割り当て可能となる。