タグ: cgroup v2

  • Linux cgroup v2のCPU制御、上限時間と配分の重みの違い

    Linux cgroup v2のCPU制御、上限時間と配分の重みの違い

    同じLinuxサーバーで二つの処理を動かすとき、「片方へ多くのCPU時間を配ること」と「片方が使えるCPU時間に上限を置くこと」は別の操作です。この違いを見落とすと、配分の重みを上げたのに処理が進まない、あるいは軽い処理まで上限に抑えられる、といった状況を読み違えます。

    cgroup v2は、プロセスをグループにまとめ、階層に沿って資源の使い方を管理するLinuxの仕組みです。CPU制御にあるcpu.weightとcpu.maxは何を決めるのか。Linux 6.12の公式文書をもとに、時間の単位と小さな配分例から整理します。ここでは通常のスケジューリング方針で動く処理を対象にし、リアルタイム処理は扱いません。[1][2]

    簡単にまとめると?

    • cpu.weightは、同じ親の下でCPUを使おうとしているグループ同士の配分比です。固定のCPU使用率や、処理速度の保証ではありません。
    • cpu.maxは、一定期間に使えるCPU時間の上限を指定します。複数のCPUで同時に動くと、その時間を合計して消費します。
    • 重みを増やしても、自分や親の時間上限は超えられません。比較するときは設定値だけでなく、使えるCPU、上位の制限、抑制の記録を一緒に見ます。

    cpu.weightは、競合している相手との比率

    CPUで実行する準備ができている処理が複数あれば、どれに実行時間を配るかを決める必要があります。cpu.weightは、その配分に使う相対的な重みです。同じ親を持ち、その時点で資源を使える子グループの重みを合計し、それぞれの割合に応じて配分します。通常の、cpu.idle=0のグループでは範囲が1〜10,000、既定値は100です。[1]

    例えば、同じ一つの論理CPUを使う兄弟グループAとBを考えます。Aの重みを100、Bを200にし、両方が常に実行可能で、ほかに競合する処理や帯域上限がないとします。配分モデル上の比率は、Aが100÷300で約3分の1、Bが200÷300で約3分の2です。これは十分な時間で見た配分を考えるための計算例で、100ミリ秒ごとに必ずその通りになる実測結果ではありません。

    ここでBが入出力待ちなどでCPUを使わなくなれば、Aは空いた時間も使えます。重み100が「CPUを100%使う」、あるいは「上限は3分の1」という意味ではないためです。また、Bの重みを2倍にしたことから、同じ仕事が必ず半分の時間で終わるとも言えません。CPUで処理する時間以外に待ちがあれば、その部分は配分比だけでは縮まりません。

    cpu.maxは、期間ごとに使うCPU時間の予算

    cpu.maxは「使えるCPU時間の上限」と「その期間」を、二つの値で表します。順番はMAX PERIODで、どちらもマイクロ秒です。1,000マイクロ秒が1ミリ秒なので、200000 100000なら、100ミリ秒の期間に合計200ミリ秒分のCPU時間を使える設定です。[1]

    経過する時間よりCPU時間が多くなるのは、複数のCPUで同時に実行できるからです。二つの論理CPUで100ミリ秒ずつ実行すれば、合計は200ミリ秒になります。上限÷期間の200,000÷100,000=2は、平均で論理CPU二つ分に相当する実行時間を示します。「特定のCPUを二つ専有する」という指定ではありません。[2]

    逆に、実行可能なスレッドが一つしかなければ、そのスレッドが二つのCPUで同時に走るわけではありません。使ってよい時間に余裕があっても、処理を並行して進められなければ使い切れません。また、割り当てられるCPUの範囲はcpusetなど別の設定にも左右されます。cpuset.cpus.effectiveは、そのグループに実際に認められたCPUの一覧です。[1]

    既定値のmax 100000は、そのグループ自身の帯域上限を設けない設定です。maxにしても親の上限は残り、空いているCPU時間や実行できるスレッド数が増えるわけではありません。

    並列に使うほど、同じ時間予算を早く消費する

    同じ200000 100000でも、四つのスレッドが四つの論理CPUで一斉に動けば、理想化した計算では50ミリ秒で合計200ミリ秒分を消費します。その後も実行したい処理が残っていれば、予算の補充まで抑制される場面があります。この上限による実行の抑制をスロットリングと呼びます。

    帯域制御は、グループの時間予算をCPUごとの実行待ち行列へ小分けに渡します。追加の時間を渡せなくなると、そのグループの処理は実行を抑えられ、次の期間で予算が補充されます。したがって、平均でCPU二つ分という上限でも、四つで短く動いて待つ形と、二つで長く動く形では、処理が進むタイミングが変わり得ます。[2]

    50ミリ秒という値は、常時実行可能な四つのスレッドが待たずに走る、という説明用の計算です。実際にはほかの処理との競合や時間予算の小分け配分があります。さらに、CPUごとに残った小さな未使用枠が次の期間へ持ち越される例外や、cpu.max.burstで蓄積した未使用枠を一時的に使う機能もあります。本文の単純な計算では追加のバースト枠を使わず、残枠の持ち越しも省いています。単一期間の厳密な実行波形を再現したものではありません。[1][2]

    重みを上げても、上限を超える許可にはならない

    AとBが同じ一つの論理CPUを使う例に戻ります。次の表は、ほかの競合や親の制限がなく、Aは常に実行可能という条件で、設定の意味を比較したものです。性能測定ではありません。

    同じ親を持つA・Bの配分例。重みはA=100、B=200。Bの動作状態とAの上限だけを変える。
    条件 Aが使える時間の考え方 判断のポイント
    A・Bとも実行可能、帯域上限なし 配分モデルでは約3分の1 重みは競合する相手との比率
    BはCPUを使わず、Aの帯域上限なし 空いたCPU時間も使える 3分の1に固定されない
    BはCPUを使わず、Aに20000 100000の上限 設定上は100ミリ秒につき20ミリ秒分 相手が休んでも、自分の上限は残る

    最後の条件でAの重みを増やしても、20ミリ秒分という自分の時間予算は変わりません。CPUが空いて見えるのに処理が止まる場合、競合に負けているのか、上限へ達したのかを分ける必要があります。

    親の制限も同様です。子グループに時間予算が残っていても、親が全体の予算を使い切れば、その子は親の予算が補充されるまで実行を抑えられます。また、異なる親の下にあるグループ同士では、末端の重みだけを比べても全体の配分比は分かりません。資源は階層に沿って配られるためです。[1][2]

    設定の目的と、実際の待ちを分けて確認する

    混雑時にどちらへ多くの時間を配るかを決めたいなら、cpu.weightが扱う問いです。一方、空いているときも含めてグループのCPU時間を制限したいなら、cpu.maxが扱う問いになります。ただし、上限を低くすることと、個々の要求が早く終わることは同じではありません。平均の使用量が抑えられても、上限に達した後の待ちが応答時間へ影響する場合があります。

    確認には、対象グループとその親の設定に加え、cpu.statの使用時間やスロットリングの記録を使えます。cgroup v2では、usage_usecがCPU使用時間、nr_periodsが帯域制御の期間数、nr_throttledが抑制の発生した期間数、throttled_usecが抑制時間に関わる統計です。時間の単位はマイクロ秒です。稼働開始からの合計だけで比較せず、同じ観測区間の前後の差を取り、要求の応答時間も別に測ると、設定と症状の関係を追いやすくなります。[1][2][3]

    ここで、抑制が発生した期間数を「遅くなった要求の件数」と読み替えたり、抑制時間をそのまま一つの要求の遅延とみなしたりしないことが大切です。CPU時間が同じでも、CPUの動作周波数や処理内容によって進む仕事量は変わります。重みは相手との配分、上限は時間の予算、応答時間は利用者が待った結果です。この三つを分けると、増やすべきものが配分なのか予算なのか、それ以外の待ちを調べるべきかを判断しやすくなります。

    参考資料

    Linux 6.12の公式文書と同版の原文を参照しています。表と時間計算は仕様を説明するための例であり、実機の設定変更や性能測定は行っていません。

    1. The Linux Kernel documentation, Control Group v2。What is cgroup、Resource Distribution Models — Weights、CPU、CPU Interface Files、Cpuset Interface Files。補助照合:v6.12の文書原文。
    2. The Linux Kernel documentation, CFS Bandwidth Control。帯域制御の仕組み、Statistics、Hierarchical considerations、CFS Bandwidth Quota Caveats、Examples。管理ファイル名と統計の単位は文書内のcgroup v1表記を流用せず、上記cgroup v2文書と対応させています。補助照合:v6.12の文書原文。
    3. Linux v6.12, kernel/sched/fair.c。do_sched_cfs_period_timerでのnr_periodsとnr_throttledの更新。抑制が発生した期間を数えることの補助確認。
  • Linux PSIで見る処理の待ち、CPU利用率と何が違うのか

    Linux PSIで見る処理の待ち、CPU利用率と何が違うのか

    サーバーのCPU利用率が低いのに、処理が遅い。そんなとき、空いているCPUだけを見ても、仕事が進まない理由はわかりません。処理はCPUの順番を待つこともあれば、メモリを確保するための回収処理や、ストレージとの入出力で足止めされることもあります。

    LinuxのPSI(Pressure Stall Information)は、CPU・メモリ・入出力の資源待ちが、仕事の進行にどれだけ影響しているかを見る仕組みです。CPUを使った時間と、資源が足りず進めなかった時間を並べると、「まだ余裕がある」という判断を一段深く確かめられます。ここではLinux v6.12の公式文書と実装を基に、数値の読み方と監視の注意点を整理します。表示例は説明用に作ったもので、実機の測定結果ではありません。[1][2]

    簡単にまとめると?

    • CPU利用率にPSIを加えると、資源を使った時間と、資源待ちで仕事が進まなかった影響を分けて調べられます。
    • someとfullは待ちの広がりを見る指標ですが、対象範囲が重要です。システム全体のCPUのfull=0を、待ちがない証拠にはできません。
    • 平均値は%、累積値はマイクロ秒です。短い待ちを知らせるトリガーには別の監視窓があり、平均値のしきい値判定と同じものではありません。

    CPUを使った時間と、仕事が待った時間

    CPU利用率は、CPUが何をしていたかを捉える指標です。その基になる/proc/statには、利用者のプログラム、カーネルの処理、アイドルなどに費やしたCPU時間が記録されます。一方、PSIが見るのは、資源の取り合いによって実行の機会が失われる側面です。両者は同じ「負荷」を別名で表示しているわけではありません。[2][3]

    たとえば、処理に必要なデータがストレージから届かなければ、その仕事はCPUを使い続けられません。CPU利用率だけなら余力に見えても、入出力の待ちによって進行が妨げられている可能性があります。逆にCPUがよく使われていても、仕事が順調に進んでいるかは別に確かめる必要があります。

    PSIのシステム全体の情報は、次の三つのファイルに分かれています。

    /proc/pressure/cpu
    /proc/pressure/memory
    /proc/pressure/io

    cpuはCPUの実行機会、memoryはメモリ資源、ioは入出力に関わる待ちを扱います。なお、ファイルが見当たらないことは、待ちがゼロという意味ではありません。カーネルがPSIに対応する設定で構築されているか、有効化されているかを先に確かめます。[1][6]

    someとfullは、対象範囲と一緒に読む

    まず1CPU上の状態で考えると、someは、その資源を待っている仕事が一つ以上ある状態です。ほかの仕事は進めている場合も含みます。fullは、待つ仕事があるうえに、その資源について前進できる仕事が残っていない状態を表します。メモリでは、メモリ回収のために動く処理を、通常の仕事が進んでいる状態と区別しています。[2]

    ここで注意したいのが、複数CPUの集計です。実装はCPUごとの状態を追い、仕事が存在した時間で重みを付けて、全体の圧迫度を近似します。表示されたfullを「サーバーの全CPUが同時に止まった時間」、someを「全スレッドの待ち時間の合計」と読むのは適切ではありません。また、fullの待ちはsomeと重なるため、二つを足して待ちの総量にはできません。[2]

    特にCPUのfullは、システム全体とcgroupで扱いが異なります。cgroupは、関連するプロセスをまとめ、資源の使用量や上限を管理するLinuxの仕組みです。cgroup v2では、対象グループのcpu.pressureなどから、そのグループのPSIを読めます。[1][4]

    Linux v6.12のシステム全体の/proc/pressure/cpuでは、fullは未定義としてゼロが返されます。文書は、Linux 5.13以降に出力されるこの欄を互換性のためゼロにしていると説明しています。このゼロから「すべての仕事が順調だ」とは判断できません。一方、cgroup内では、ほかのグループがCPUを使っていたり、cpu.maxの上限によって実行が抑えられたりすると、CPUのfullが生じ得ます。[1][2]

    平均の%と、累積のマイクロ秒を分ける

    次は、メモリのPSIを説明するための架空の表示例です。totalも含め、実測した値ではありません。

    some avg10=12.50 avg60=4.00 avg300=1.20 total=3250000
    full avg10=2.00 avg60=0.80 avg300=0.25 total=500000

    各欄が表すものを、単位と一緒に整理します。

    PSIの表示欄の読み方(Linux v6.12の文書・実装を基に作成)
    表示欄 単位 わかることと注意点
    avg10 % 10秒を目安とした短期の傾向。直近の変化に比較的早く反応する。
    avg60・avg300 % 60秒・300秒を目安とした、より長い傾向。短い変化の影響はならされる。
    total マイクロ秒(µs) 対象範囲で集計した圧迫時間の累積。差分から任意の観測区間を調べられる。個々の要求の応答時間ではない。

    平均値の「10秒」などは、そこから前を切り捨てる固定区間の単純平均ではありません。Linux v6.12の実装では、過去の値の影響が徐々に小さくなる指数移動平均を使います。したがってavg10=12.50を、「直前10秒のうち、ちょうど1.25秒待った」と言い換えることはできません。短期のavg10が長期のavg300より高ければ、最近の圧迫が強まった可能性を調べる手掛かりになります。[2][5]

    任意の区間を見たい場合は、同じ対象・同じ行のtotalの差を取ります。たとえば上のsomeが、正確に10秒後に4750000へ増えたと仮定します。増分は1,500,000 µs、つまり1.5秒です。観測した10秒で割ると、その区間のPSI圧迫時間の割合は15%と計算できます。これはavg10を逆算した値でも、処理ごとの待ち時間を合算した値でもありません。[1][2]

    差分を取る前には、読み取りの間隔と対象をそろえます。再起動やcgroupの作り直しをまたいで、別のカウンターを引き算しないことも必要です。監視ソフトで扱う場合も、割合と累積時間を同じ系列として混ぜないようにします。

    短い待ちを知らせる監視窓は、avg10とは別

    平均値は傾向を見るのに便利ですが、短い待ちの増加を、別の時間幅で検知したいこともあります。PSIは、そのためのトリガーを登録できます。次は、メモリのsomeに登録する条件の例です。自動実行するコマンドではなく、書き込む設定文字列を示しています。

    some 200000 2000000

    二つの数値の単位は、どちらもマイクロ秒です。意味は「2秒の監視窓に、200ミリ秒の圧迫時間が蓄積したら知らせる」。比率にすれば10%ですが、avg10が10%以上になったら知らせる設定とは違います。2秒は監視する時間幅で、10秒は先ほどの平均値の尺度だからです。ここで選んだ数値は読み方の説明用であり、あらゆるサービスに適した警報値ではありません。[1][2]

    登録には、対象のPSIファイルを開き、そのファイル記述子へ条件を書き込みます。ファイル記述子とは、プログラムが開いたファイルを扱うための番号です。監視プログラムは同じ記述子を開いたまま、poll()などで通知を待ちます。閉じるとトリガーも解除されるため、echoで一度書くだけでは継続監視になりません。複数のトリガーには、それぞれ別のopen()が必要です。[1]

    利用できる監視窓には権限による条件もあります。Linux v6.12では、CAP_SYS_RESOURCE権限を持たない監視の場合、窓は2秒の倍数でなければなりません。上限は10秒です。上の例はこの窓の条件に収まりますが、対象ファイルへの書き込み権限などは別に必要です。また、権限によって監視の集計経路が異なるため、通知が常に同じ間隔や精度で届くとは仮定できません。[1][2]

    トリガーの窓内時間は推定を含み、通知は同じ監視窓の長さにつき最大1回へ制限されます。一つの待ちが発生するたびに届く通知でも、すべての遅延事象を漏れなく記録する仕組みでもありません。実運用では、使っているカーネルの版・設定・権限で監視が成立することを確かめてから、サービス側の遅延と照合します。[2]

    PSIを、原因を絞る次の観測につなげる

    PSIの価値は、一つの値でサーバーの良否を決めることよりも、次に何を調べるかを選びやすくする点にあります。システム全体の数値と、遅い処理が属するcgroupの数値を、同じ時間帯で見比べます。全体では目立たない圧迫が、特定のグループに集中している可能性もあるからです。

    cgroupのCPU圧迫が高ければ、CPUの取り合いに加えて、そのグループの上限も確認します。cpu.maxは利用可能なCPU時間の上限と期間、cpu.statのnr_throttledやthrottled_usecは、CPUコントローラーによる実行抑制を調べる材料です。PSIだけを見て、CPUを増設すれば解決すると結論づけるのは早計です。[2][4]

    メモリや入出力の圧迫が高い場合も、処理の応答時間、メモリ回収、ストレージの状態を突き合わせます。なお、CPU統計のiowaitはPSIのioと同じ指標ではありません。公式文書もiowaitの算定上の限界を説明しているため、同じ値になることを前提に比較しないようにします。[3]

    PSIが低くても、アプリケーション内部の処理や外部サービスの応答まで良好だと保証されるわけではありません。PSIはCPU・メモリ・入出力の資源圧迫を見る手掛かりです。「CPUはどれだけ使われたか」に「どの範囲の仕事が、何を待っていたか」を重ねることで、余力の判断も、遅さの切り分けも具体的になります。

    出典

    1. The Linux Kernel documentation, “PSI – Pressure Stall Information”、Linux v6.12。表示形式、システム全体とcgroupの対象範囲、トリガーの利用方法。監視窓の下限について文書と同版実装に差があるため、本文の例は両方で確認できる2秒の窓としています。
    2. Linux v6.12, kernel/sched/psi.c。some/fullのモデル、複数CPUの集計、平均値、CPU fullの出力、トリガーの条件・集計・通知制限。
    3. Linux v6.12, “The /proc Filesystem”、/proc/statの節。CPU時間の区分とiowaitの制約。
    4. Linux v6.12, “Control Group v2”、CPUインターフェースの節。cpu.max、cpu.stat、cpu.pressure。
    5. Linux v6.12, include/linux/sched/loadavg.h。PSIの平均値計算から呼ばれるcalc_load()の式。
    6. Linux v6.12, init/Kconfig、PSI・PSI_DEFAULT_DISABLED。構築時設定と有効化条件。資料確認日:2026年10月14日。