linux:kernel:cgroup:memory.txt翻訳

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
linux:kernel:cgroup:memory.txt翻訳 [2013/03/28 11:31] – [5.5. usage_in_bytes] tenforwardlinux:kernel:cgroup:memory.txt翻訳 [2013/08/21 15:43] (現在) – [11. メモリプレッシャー] tenforward
行 1: 行 1:
-<color red>自分用の適当翻訳ですので細かい所は間違いがあると思います.原文をお読みください.</color>+<color red>自分用の適当翻訳ですので細かい所は間違いがあると思います.原文 (Documentation/cgroups/memory.txt) をお読みください.</color> 
 + 
 +多分,3.10 ベース.
  
 ====== メモリリソースコントローラ ====== ====== メモリリソースコントローラ ======
行 36: 行 38:
   * タスクを移動することによりカウントの移動 (再カウント) が選択可能   * タスクを移動することによりカウントの移動 (再カウント) が選択可能
   * 使用量のしきい値の通知   * 使用量のしきい値の通知
 +  * メモリプレッシャーの通知
   * oom-killer が knob と oom-notifier を無効にすること   * oom-killer が knob と oom-notifier を無効にすること
   * root cgroup には制限のコントロールがない   * root cgroup には制限のコントロールがない
行 61: 行 64:
  memory.use_hierarchy            # カウントの階層構造の有効/無効を設定する/表示する  memory.use_hierarchy            # カウントの階層構造の有効/無効を設定する/表示する
  memory.force_empty              # 親グループへチャージを強制移動するトリガ  memory.force_empty              # 親グループへチャージを強制移動するトリガ
 + memory.pressure_level           # メモリプレッシャー通知を設定する
  memory.swappiness               # vmscan の swappiness パラメータを設定する/表示する  memory.swappiness               # vmscan の swappiness パラメータを設定する/表示する
                                  (See sysctl's vm.swappiness)                                  (See sysctl's vm.swappiness)
行 144: 行 148:
 ==== 2.3. 共有メモリのカウント ==== ==== 2.3. 共有メモリのカウント ====
  
-共有メモリはファーストタッチアプローチ (first touch approach) の原則でカウントされます.最初にページにタッチした cgroup がページをカウントします.この原則の背後にある原則は,共有メモリを積極的に使う cgroup に対して,最終的にチャージがなされるということです (一旦,チャージされた cgroup からのアンチャージは,メモリが圧迫されている時に起こります).+共有メモリはファーストタッチアプローチ (first touch approach) の原則でカウントされます.最初にページにタッチした cgroup がページをカウントす.この原則の背後にある原則は,共有メモリを積極的に使う cgroup ,最終的にチャージを得るということです (一旦,チャージされた cgroup からのアンチャージは,メモリが圧迫されている時に起こります).
  
 しかし,Section 8.2 を参照すること: 他の cgroup からタスクが移動する際,もし move_charge_at_immigrate が選択されている場合は,そのページは新しいグループに再チャージされる. しかし,Section 8.2 を参照すること: 他の cgroup からタスクが移動する際,もし move_charge_at_immigrate が選択されている場合は,そのページは新しいグループに再チャージされる.
行 360: 行 364:
 ==== 5.4. failcnt ==== ==== 5.4. failcnt ====
  
-メモリ cgroup は memory.failcnt と memory.memsw.failcnt を提供します.この failcnt(==failure count) は使用量カウンタが制限にヒットした回数を表します.メモリ cgroup は制限にヒットしたとき,failcnt の値が増え,その配下のメモリが回収されるだろう.+メモリ cgroup は memory.failcnt と memory.memsw.failcnt を提供す.この failcnt(==failure count) は使用量カウンタが制限にヒットした回数を表します.メモリ cgroup は制限にヒットしたとき,failcnt の値が増え,その配下のメモリが回収されるだろう.
  
 failcnt は 0 を failcnt ファイルに書き込むことによりリセットできる. failcnt は 0 を failcnt ファイルに書き込むことによりリセットできる.
行 368: 行 372:
 効率性のために,他のカーネルコンポーネントのように,メモリ cgroup は不要なキャッシュラインのフォールスシェアリングを防ぐためにいくつか最適化がなされている.usage_in_bytes はメソッドの影響を受け,メモリ (またはスワップ) の使用量の正確な値を表示しない.効率的なアクセスのためにあまり正確でない値となる.(もちろん,必要な時,それは同期される)もしより正確なメモリ使用量を知りたい時は,memory.stat 内の RSS+CACHE(+SWAP) の値を使用するべきである. 効率性のために,他のカーネルコンポーネントのように,メモリ cgroup は不要なキャッシュラインのフォールスシェアリングを防ぐためにいくつか最適化がなされている.usage_in_bytes はメソッドの影響を受け,メモリ (またはスワップ) の使用量の正確な値を表示しない.効率的なアクセスのためにあまり正確でない値となる.(もちろん,必要な時,それは同期される)もしより正確なメモリ使用量を知りたい時は,memory.stat 内の RSS+CACHE(+SWAP) の値を使用するべきである.
  
 +==== 5.6. numa_stat ====
 +
 +これは numa_maps と同様であるが,memcg ごとの規則によって操作される.ページはどの物理的なノードからも割り当て可能であるので,これは memcg 内で numa に関する情報を可視化するのに便利である.ユースケースの一つは,アプリケーションの CPU 割り当ての情報とこの情報を合わせることにより,アプリケーションパフォーマンスを評価することがある.
 +
 +memcg ごとに,ノードごとの "total","file", "anon", "unevictable" ページを提供する.memory.numa_stat の出力フォーマットは:
 +
 +<code>
 +total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
 +file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
 +anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
 +unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
 +</code>
 +
 +ここで total = file + anon + unevictable である.(訳注: unevictable は回収できないページ)
 +
 +===== 6. 階層構造サポート =====
 +
 +メモリコントローラは深い階層構造と階層構造のアカウンティングをサポートしている.階層構造は cgroup ファイルシステム内に適切な cgroup を作成することにより作成される.例として考えられるのは,以下のような cgroup ファイルシステムの改造構造である.
 +
 +<code>
 +               root
 +             /  |   \
 +            /      \
 +              b     c
 +                      | \
 +                      |  \
 +                      d   e
 +</code>
 +
 +上記の図で,階層構造のアカウンティングが有効になっている場合,e の全てのメモリ使用量は root まで祖先をさかのぼってカウントされる (c と root).階層構造のアカウンティングを有効にするのは memory.use_hierarchy を有効にする.もし,祖先の 1 つが制限を超えた場合,回収アルゴリズムはその祖先とその祖先の子供のタスクから回収を行う.
 +
 +==== 6.1. 階層構造のアカウンティングと回収を有効にする ====
 +
 +デフォルトでは,メモリ cgroup は階層構造機能が無効になっている.このサポートを有効にするには,root cgroup の  memory.use_hierarchy ファイルに 1 を書き込む.
 +
 +<code># echo 1 > memory.use_hierarchy</code>
 +
 +この機能を無効にするには
 +
 +<code># echo 0 > memory.use_hierarchy</code>
 +
 +注意1: 有効化/無効化は,cgroup が既に配下に他の cgroup を持つ時,親の cgroup の use_hierarchy が有効になっている場合は失敗する.
 +
 +注意2: panic_on_oom が 2 に設定されている時,いずれかの cgroup で OOM イベントが発生した場合,全システムがパニックとなる.
 +
 +===== 7. ソフトリミット =====
 +
 +ソフトリミットは以下のようにコマンドを使うことで設定できる.(この例ではソフトリミットを 256MiB と仮定している)
 +
 +<code># echo 256M > memory.soft_limit_in_bytes</code>
 +
 +これを 1G に変えたい場合は,いつでも以下のように実行することが可能である.
 +
 +<code># echo 1G > memory.soft_limit_in_bytes</code>
 +
 +注意1: ソフトリミットは長い時間に渡って効果がある.これはメモリ cgroup 間でバランスを取るためにメモリの回収が呼び出されるからである.
 +
 +注意2: ソフトリミットはハードリミットよりも常に少ない値で設定することを推奨する.さもないとハードリミットに先に到達してしまう.
 +
 +===== 8. タスクマイグレーション時のチャージの移動 =====
 +
 +ユーザはタスクマイグレーションと同時にタスクに関係するチャージを移動することが可能である.これは元の cgroup からタスクのページをアンチャージして,新しい cgroup にチャージするということである.この機能は CONFIG_MMU でない環境ではサポートされない.ページテーブルが欠如しているためである.
 +
 +==== 8.1. インターフェース ====
 +
 +この機能はデフォルトでは無効になっている.目的の memory.move_charge_at_immigrate に書き込むことで有効化,無効化が可能である.
 +
 +もし有効化したい場合:
 +
 +<code># echo (some positive value) > memory.move_charge_at_immigrate</code>
 +
 +注意: move_charge_at_immigrate のぞれぞれのビットはどの種類のチャージを移動させるべきかという意味を持っている.8.2 を参照.
 +
 +注意: チャージは mm->owner を移動させたときのみ移動する.言い換えると,スレッドグループのリーダーを移動させたときのみ移動する.
 +
 +注意: 移動先の cgroup にタスクの充分なスペースが見つけられない場合,メモリを回収することによりスペースを作成しようとする.もし充分なスペースを作ることが出来ない場合は,タスクマイグレーションは失敗する.
 +
 +注意: 大量のチャージを移動させる場合,数秒かかる場合がある.
 +
 +==== 8.2. 移動するチャージのタイプ ====
 +
 +move_charge_at_immigrate のそれぞれのチャージはどのタイプのチャージを移動させるべきかという意味を持つ.しかしいずれにしても,ページやスワップのアカウントは,タスクの現在の (古い) メモリ cgroup へチャージされた時だけ移動させることができることに注意しなければならない.
 +
 +^ bit ^ どのタイプのチャージが移動するか ^
 +| 0 | ターゲットとなるタスクが使う匿名ページとそれのスワップのチャージ.スワップのチャージを移動できるには,スワップ拡張 (2.4参照) を有効にしなければならない |
 +| 1 | ターゲットとなるタスクによってマッピングされたファイルページ (通常のファイル,tmpfsファイル (e.g. ipc 共有メモリ),tmpfs ファイルのスワップ).匿名ページとは違って,タスクがマップした範囲のファイルページ (とスワップ) はページフォールトが起こってない場合でも移動するだろう.すなわち,そのタスクの "RSS" でないかもしれず,同じファイルにマップされた他のタスクの "RSS" であるかもしれない.そして,ページのマップカウントは無視される (ページは page_mapcount(page) > 1 であっても移動する可能性がある).|
 +
 +(訳注) 0=無効,1=匿名ページとそのスワップ,2=ファイルページ,3=両方指定
 +==== 8.3. TODO ====
 +  * チャージを移動させる全ての操作は cgroup_mutex 配下で実行される.これは,mutex を長時間保持する良くない振るまいである.なので技が少し必要かもしれない.
 +
 +===== 9. メモリのしきい値 =====
 +
 +メモリ cgroup は cgroup 通知 API (cgroups.txt 参照) を使ったメモリのしきい値を実装している.これにより複数のメモリやmemswのしきい値を登録でき,それが超えた場合に通知を受けとることができる.
 +
 +しきい値を登録するには,アプリケーションは以下のようにしなければならない.
 +
 +  * eventfd(2) を使って eventfd を作成する
 +  * memory.usage_in_bytes か memory.memsw.usage_in_bytes を open する
 +  * "<event_fd> <fd of memory.usage_in_bytes> <threshold>" のような文字列を cgroup.event_control に書き込む
 +
 +===== 10. OOM コントロール =====
 +
 +memory.oom_control ファイルは OOM 通知や他のコントロールを行うためのファイルである.
 +
 +メモリ cgroup は cgroup 通知 API (cgroups.txt を参照) を使った OOM 通知を実装している.これにより複数の OOM 通知配送を登録でき,OOM が起こった時に通知を受けとることができる.
 +
 +通知を登録するには,アプリケーションは以下のようにしなければならない.
 +
 +  * eventfd(2) を使って eventfd を作成する
 +  * memory.oom_control ファイルを open する
 +  * "<event_fd> <fd of memory.oom_control>" というような文字列を cgroup.event_control に書き込む
 +
 +アプリケーションは OOM が起こると eventfd を通して通知を受けとる.OOM 通知は root cgroup では機能しない.
 +
 +OOM-killer を無効にするには memory.oom_control ファイルに "1" を書き込む事で可能となる.
 +
 +<code>#echo 1 > memory.oom_control</code>
 +
 +この操作は階層構造のトップの cgroup でのみ可能である.OOM-killer が無効化された場合,割り当て可能なメモリを要求したとき,cgroup 配下のタスクは,メモリ cgroup の OOM-waitqueue 内でハングアップするかスリープするだろう.
 +
 +このようなタスクを実行するには,cgroup の OOM ステータスを以下のように緩和する必要がある.
 +  * 制限を大きくするか,使用量を削減する
 +  * いくつかのタスクを他のグループに移動させ,アカウンティングも移動させる
 +  * いくつかファイルを削減する (tmpfs 上の?)
 +
 +そして,タスクを停止させ,再度実行する.
 +
 +以下を見ることで,OOM の現在の状態を見ます.
 +  * oom_kill_disable 0 or 1 (1 の時,oom-killer は無効化されている)
 +  * under_oom 0 or 1 (1 の時,メモリ cgroup は OOM 状態にあり,タスクは停止している可能性がある)
 +
 +===== 11. メモリプレッシャー =====
 +
 +プレッシャーレベルの通知はメモリアロケーションのコストをモニタリングするのに使う事ができる.これはプレッシャーをもとにしており,アプリケーションは自身のメモリリソースに様々な管理戦略を実装することが可能になる.プレッシャーレベルは以下のように定義される.
 +
 +"low" レベルは,システムが新しいアロケーションのためにメモリを回収している事を意味する.この回収の動きをモニタリングする事はキャッシュレベルを良好に保つのに役に立つ可能性がある.通知があると,プログラム (一般的には "アクティビティ・マネージャ") は vmstat を解析し,あらかじめ何らかの動作を行う事が可能になる (例えば,早めに重要でないサービスを停止するなど).
 +
 +"medium" レベルは,システムが中位のメモリプレッシャー状態にあることを意味する.システムは swap し,アクティブなファイルキャッシュをページアウトするなどしている可能性がある.このイベントで,アプリケーションは vmstat/zoneinfo/memcg や,簡単に再構築できたりディスクから再読み込みすれば良い内部的なメモリ使用の統計値と空きリソースのさらなる解析を決定する可能性がある.
 +
 +"critical" レベルは,システムが頻繁にスラッシングを起こしている事を意味する.これはまさに out of memory(OOM) しようとしているところであるか,OOM killer が起動しようとしている所である.アプリケーションは,システムを助ける事ができることなら何でもすべきである.この状態では vmstat や他の統計値の状態を見るには遅すぎであり,すぐに何らかのアクションを起こす事が賢明である.
 +
 +イベントは,処理されるまで上流に伝搬する.すなわちイベントは貫通はしないということである.これがどういうことかを以下にしめす.例えば,3 つの cgroup A->B->C が存在するとする.さてここで cgroup A, B, C にイベントリスナーを設定し,グループ C がある種のプレッシャー状態にあるとする.この状況で,グループ C のみが通知を受け取る.すなわち A, B は通知を受け取らない.これはメッセージの過度の「ブロードキャスティング」を防ぐためである.過度のブロードキャスティングは,システムの稼働を阻害し,メモリが少なかったりスラッシング状態にある場合に特に悪い影響を与える.なので,cgroup をきちんと構造化したり,イベントを手動で伝搬するようにする (もしくは,パススルーイベントを自分で実装するように求めたり,なぜ必要なのかの説明を求めたりする).
 +
 +memory.pressure_level ファイルは eventfd を設定するためだけに使われる.通知を登録するために,アプリケーションは
 +
 +  - eventfd(2) を使って eventfd を作成する
 +  - memory.pressure_level を open する
 +  - "<event_fd> <fd of memory.pressure_level> <level>" というような文字列を cgroup.event_control に write する
 +
 +アプリケーションは,メモリプレッシャーが指定したレベル (か高いレベル) に達した時,eventfd を通して通知を受け取る.memory.pressure_level に対する read/write 操作は実装されていない.
 +
 +テスト:
 +
 +ここに小さなサンプルスクリプトがある.これは新しい cgroup を作成し,メモリリミットを設定し,cgroup に通知を設定し,それから子供の cgroup に対して深刻なプレッシャーを与えるスクリプトである.
 +
 +<code>
 +# cd /sys/fs/cgroup/memory/
 +# mkdir foo
 +# cd foo
 +# cgroup_event_listener memory.pressure_level low &
 +# echo 8000000 > memory.limit_in_bytes
 +# echo 8000000 > memory.memsw.limit_in_bytes
 +# echo $$ > tasks
 +# dd if=/dev/zero | read x
 +</code>
 +
 +(多数の通知が予測され,最終的には oom-killer が発動するだろう)
 +
 +
 +===== 12. TODO =====
 +
 +  - huge ページのアカウンティングサポート (分離したコントローラとして)
 +  - cgroup ごとのスキャナーが最初に共有されていないページを回収するようにする
 +  - コントローラに共有ページに対するアカウントを教える
 +  - 制限には達していないが,使用量が制限に近づいている時に,バックグラウンドで回収を開始する
 +
 +===== Summary =====
 +
 +全体的に,メモリコントローラは stable なコントローラであり,コミュニティ内で広く議論とコメントがなされてきた
 +
 +===== References =====
 +
 +  - Singh, Balbir. RFC: Memory Controller, http://lwn.net/Articles/206697/
 +  - Singh, Balbir. Memory Controller (RSS Control), \\ http://lwn.net/Articles/222762/
 +  - Emelianov, Pavel. Resource controllers based on process cgroups http://lkml.org/lkml/2007/3/6/198
 +  - Emelianov, Pavel. RSS controller based on process cgroups (v2) http://lkml.org/lkml/2007/4/9/78
 +  - Emelianov, Pavel. RSS controller based on process cgroups (v3) http://lkml.org/lkml/2007/5/30/244
 +  - Menage, Paul. Control Groups v10, http://lwn.net/Articles/236032/
 +  - Vaidyanathan, Srinivasan, Control Groups: Pagecache accounting and control subsystem (v3), http://lwn.net/Articles/235534/
 +  - Singh, Balbir. RSS controller v2 test results (lmbench), http://lkml.org/lkml/2007/5/17/232
 +  - Singh, Balbir. RSS controller v2 AIM9 results http://lkml.org/lkml/2007/5/18/1
 +  - Singh, Balbir. Memory controller v6 test results, http://lkml.org/lkml/2007/8/19/36
 +  - Singh, Balbir. Memory controller introduction (v6), http://lkml.org/lkml/2007/8/17/69
 +  - Corbet, Jonathan, Controlling memory use in cgroups, http://lwn.net/Articles/243795/
  
  • linux/kernel/cgroup/memory.txt翻訳.1364470306.txt.gz
  • 最終更新: 2013/03/28 11:31
  • by tenforward