lkml でお勉強 (その1-2)
○ ページフレーム回収処理のパフォーマンスアップの話 (後編)
前回は kosaki さんが先日投稿された patch の中身を理解する上でのバッググラウンドについての解説を行った。
今回はその patch の内容を見て、中身 (*1) の処理の考察を行ってゆく。
内容的には基本的に追加されている項目は無く、中身の処理を入れ換えているだけである。
注目すべきなのは、isolate_pages() メソッドが 0 を返したときに shrink_inactive_list() の処理を中断している事である。
同氏のコメント
If sc->isolate_pages() return 0, we don't need to call shrink_page_list().
について、isolate_pages_global() の処理を詳細に見ながら、これがどういうことなのかを考えてみる。
isolate_pages_global() の返戻値は isolate_lru_pages() の返戻値である。ではどのような時に isolate_lru_pages() が 0 を返すのか。じっくり中身を見て行く。
isolate_lru_pages() では、第二引数で渡したページリスト (src) から、実際に回収するページフレームを第三引数で渡したページリスト (dst) に入れ換え呼び出し元に返す。
まずページリストを受け取り、対象ページリストの末尾からページを取り出し、これに対して __isolate_lru_page() を呼び出す。そして __isolate_lru_pages() が -EBUSY を返した場合、対象ページを属している lru リストの先頭に移動させて、再びリストからページを取り出して __isolate_lru_pages() を呼び出す。また __isolate_lru_pages() が 0 を返すと、対象ページを dst ページリストに追加する。
更に、回収するページフレームと 2^order の幅で隣接するページフレームを同様に走査して、回収ページフレームのリストに追加し、処理を shrink_inactive_list() に返す。
__isolate_lru_pages() ではまず、page が lru リストに繋がっているかや、動作に不整合が無いかを確かめる。不整合とは、引数で渡された動作モード mode が ISOLATE_BOTH ではなく、かつ mode (ISOLATE_ACTIVE or ISOLATE_INACTIVE) とページディスクリプタの状態フラグ (PG_active or !PG_active) が食い違っている事である。この場合には __isolate_lru_pages() は -EINVAL を返す。また、ページキャッシュからページを回収するつもりなのに、対象ページがページキャッシュに入っていなかった場合や、その逆の場合も -EINVAL を返す。そして、ページフレームが Unevictable リストに属している場合にも -EINVAL を返す。
Unevictable リストとは文字どおり、強制回収できないリストを表す。この機構は比較的最近実装されたもので、64 bit 環境で 100GB を越える大容量な RAM を搭載した環境におけるページフレーム回収コストを減らす目的で導入されている。最新のカーネルドキュメント (*2) によれば、unevictable リストに属するページは、次の 3 種類のページになる (らしい)。
・ramfs が所有するページ
・共有メモリロックのメモリリージョンにマッピングされているページ
・VM_LOCKED フラグがセットされたメモリリージョンにマッピングされているページ
これら全てのチェックに該当しない場合、対象のページは回収目的としているページという事になる。__isolate_lru_pages() はここで page を引数に page_is_file_cache() を実行する。
page_is_file_cache() は include/linux/mm.h で定義されているマクロで、引数で指定したページの参照カウンタが 0 以上の時に atomic_inc するものである。
ページフレームの参照カウンタは、どこからも利用されていない時 -1 となる。しかし、この状態のページがいきなりユーザの手元に行くことは無い。スラブキャッシュの管理下にあるがどこにも割り当てられていない場合、対象ページは利用されてはいないが参照カウンタは +1 されて 0 となる。
つまり __isolate_lru_page() 処理が -EBUSY を返す時は、対象ページフレームは空きページフレームである事を意味する。そしてその場合、呼び出し元である isolate_lru_pages() 関数は、対象ページをリストの先頭に移動させる。
この時点で kosaki さんの patch に書かれている "sc->isolate_pages() が 0 を返すとき、shrink_page_list() を呼び出す必要が無い ..." という意味がわかったと思う。
つまり isolate_pages() が 0 を返す時は、ゾーン中のページリストの中身を走査して、回収可能なページが 1 つも出力されない時なので、shrink_page_list() を呼ぶ必要は無いということである。
調べてみれば何とも無いような事だが、自分には見付けられない問題を見付けられる人間は自分の遥か上を行っているという事は間違いない。次はなるべく、自分の不得意分野の教材を探すようにする。
(*1) http://lkml.org/lkml/2009/7/15/371
(*2) Documentation/vm/unevictable-lru.txt
- Category(s)
- 学習経過
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/ohyama/lkml-304a52c95f37-305d306e1-2/tbping