/note/tech

Linux 7.0におけるPREEMPT_NONE削除問題に関するメモ

■ 1. PREEMPT_NONEとは何か

  • Linuxカーネルのプリエンプションモードの一つで、カーネルが原則としてタスクを強制中断しない設計
  • プリエンプションモードの種類:
    • PREEMPT_NONE: ユーザー空間復帰時または明示的なschedule()呼び出し時のみ切り替わる
    • PREEMPT_VOLUNTARY: cond_resched()による任意の降伏点を随所に挿入
    • PREEMPT_LAZY: 通常はNONEに近いがスケジューラ判断でプリエンプト可能
    • PREEMPT_FULL: どこでもプリエンプト可能
    • PREEMPT_RT: スピンロックを含むほぼすべてをプリエンプト可能なリアルタイム対応
  • スループット優先のサーバー向けとして長年利用されてきた

■ 2. PREEMPT_NONEが削除される理由

  • PREEMPT_RTへの統合:
    • Linuxコミュニティは長年PREEMPT_RTのメインライン統合を進めており、カーネルの設計が「どこでもプリエンプト可能」を前提とする方向に移行中
    • PREEMPT_NONEはその前提と根本的に相容れない
  • cond_resched()の乱用解消:
    • PREEMPT_NONEおよびPREEMPT_VOLUNTARYでは長時間CPUを占有するコードパスにcond_resched()を手動挿入する必要がある
    • Peter ZijlstraはこれをPREEMPT_LAZYへの移行により解消できると説明
  • コードの簡素化:
    • 4〜5種類あるプリエンプションモードをFULLとLAZYの2種類に絞ることでカーネルの複雑性を大幅削減

■ 3. 変更の経緯と「急だった」とされる根拠

  • 段階ごとの経緯:
    • 2004〜2024年: PREEMPT_RTプロジェクトが約20年を経てLinux 6.12でメインライン統合
    • 2024年9月: Linus TorvaldsがEurope Open Source SummitでPREEMPT_RTのメインライン受け入れを発表
    • 2024年11月: Linux 6.13にPREEMPT_LAZYが追加。この時点でPREEMPT_NONEは廃止されていない
    • 2026年1月: PREEMPT_NONEをLinux 7.0から廃止するパッチが投入
  • 「急だった」とされる根拠:
    • PREEMPT_LAZY追加からPREEMPT_NONE廃止まで約2ヶ月しかない
    • PostgreSQLのような高競合スピンロックワークロードへの影響が事前に検証されていなかった
    • PREEMPT_RTのメインライン化(2024年9月)からPREEMPT_NONE廃止まで1年余りという短期間
    • Linux 7.0がUbuntu 26.04 LTSに採用される予定であり企業・サーバー環境への波及が大きいタイミング

■ 4. 性能劣化の構造とPostgreSQLへの影響

  • PREEMPT_NONEの保証とPostgreSQL:
    • PostgreSQLは高競合のスピンロックを多用する設計であり「ロック保持中に中断されない」という保証が性能上クリティカル
    • PREEMPT_LAZYへの移行でAWSエンジニアがLinux 7.0リリース約2週間前に性能半減を報告
  • Zijlstraの回答とその問題点:
    • 「PostgreSQL側でRSEQ(Restartable Sequences)のタイムスライス拡張を使え」と回答
    • RSEQタイムスライス拡張自体がLinux 7.0で初めて利用可能になったばかりであり移行コストを下流に一方的に押し付けている

■ 5. カーネルとPostgreSQL開発者間の過去の議論

  • 2011年:
    • PostgreSQL開発者Robert Haasが「スピンロック保持中にプロセスがタイムスライスアウトされることが問題」と正確に分析・認識
  • 2012年:
    • Linux 3.6でのスケジューラ変更によりpgbenchが3.5比で約20%低下
    • カーネル側の議論は「これはカーネルの問題」という前提で行われPgSQL側への修正要求はなかったとLWNが明記
    • PostgreSQL開発者Josh Berkusが「アプリ修正案は機能しない。旧バージョンのカーネルに留まり続けるユーザーが大量発生するだけ」と論証
  • 2026年:
    • PREEMPT_NONEの廃止に際してカーネル開発者とPostgreSQL開発者間の事前正式調整が行われた形跡はない
    • 問題が表面化したのはAWSエンジニアがLinux 7.0リリース約2週間前にメーリングリストへ投稿したタイミング

■ 6. 「性急・強引」という評価の妥当性

  • 「性急・強引」と言える根拠:
    • 置き換え先(PREEMPT_LAZY)の実績が不十分なまま廃止が進んだ
    • 解決策として提示されたRSEQがまだ実用可能でないタイミングでPREEMPT_NONEを廃止
    • LTSとの組み合わせが最悪のタイミングとなった
  • 一概には言えない側面:
    • PREEMPT_NONEはロック保持中の割り込み排除のためカーネル全体の設計を複雑化させる面があった
    • PREEMPT_RTへの移行は20年越しで段階的に告知されており完全に唐突ではない
    • カーネル開発者の責務はシステム全体の健全化であり特定アプリケーションに合わせて設計を曲げることには限界がある
  • 本質的な問題:
    • 技術的な正誤ではなく移行コストの分担の問題
    • 設計の方向性は正当だが移行を支える十分なベンチマーク・検証・猶予期間なしに進めた点は拙速
    • 「調整の仕組みが機能しなかった」と見るのが正確な分析

■ 7. Linus Torvaldsの立場

  • 現状(2026年4月時点):
    • 問題発覚から2日時点でLinusの公式発言はなく未関与
    • Linux 7.0安定版リリースは約1〜2週間後が見込まれるリリース直前のタイミング
  • 2012年の先例:
    • 同種の問題に数時間で参加し「アイドルCPUを探すコストを削減する方向」などカーネル側での解決を主導
    • 当時の立場はZijlstraの今回の「PostgreSQL側で直せ」という回答とは対照的
  • 今後のシナリオ:
    • 楽観的: 2012年と同様に性能リグレッションを受け入れずPREEMPT_NONEのデフォルト復帰か緩和策を求める
    • 悲観的: Zijlstraの立場を支持しリリースをそのまま進める
    • 中間: 今回のリリースはそのまま出しつつ次のサイクルで緩和措置を指示する