スレッドプール設定の動的更新APIを追加

puma/puma

Pumaに、サーバー稼働中にスレッド数の最小値・最大値を動的に変更できる新しいAPIが追加されました。これにより、負荷状況に応じたスレッドプールの自動調整が可能になります。

背景

これまでPumaのスレッド数は起動時の設定で固定されており、稼働中に変更する公式な手段がありませんでした。#3658では、負荷に応じて最適なスレッド数を自動的に調整するアルゴリズムの実装に向けて、スレッド数を動的に更新するAPIが提案されています。

PR作成者の調査によると、Pumaの ThreadPool は既に @min@max を参照してスレッドの生成・削減を行う仕組みを持っているため、この値を更新するだけで動的な調整が実現できることが判明しました。

既存のアーキテクチャを活用することで、大規模な変更なしに動的調整機能を実現できる設計判断となっています。

技術的な変更

Server#update_thread_pool_min_max メソッドが新たに追加され、スレッドプールの最小値・最大値を更新できるようになりました。

def update_thread_pool_min_max(min: @min_threads, max: @max_threads)
  if min > max
    @log_writer.log "`min' value cannot be greater than `max' value."
    return
  end

  if min < 0
    @log_writer.log "`min' value cannot be less than 0"
    return
  end

  @thread_pool&.with_mutex do
    @thread_pool.min, @thread_pool.max = min, max
    @min_threads, @max_threads = min, max
  end
end

このメソッドは以下の検証を行います:

  • minmax より大きい場合は警告を出力して更新を中止
  • min が0未満の場合は警告を出力して更新を中止
  • 検証を通過した場合、mutexで保護された状態でスレッドプールと設定値の両方を更新

デフォルト引数として現在の値を使用することで、片方だけの更新も可能になっています。

プラグイン向けの制御インターフェース

ServerPluginControl クラスが新設され、プラグインがサーバーの内部状態に直接アクセスせずに設定を変更できるファサードパターンが採用されました。

class ServerPluginControl
  def initialize(server)
    @server = server
  end

  def max_threads
    @server.max_threads
  end

  def min_threads
    @server.min_threads
  end

  def update_thread_pool_min_max(min: max_threads, max: min_threads)
    @server.update_thread_pool_min_max(min: min, max: max)
  end
end

このクラスは before_thread_start フックのコールバックに渡されるようになり、プラグインから安全にスレッド設定を変更できます。

@before_thread_start.each do |b|
  begin
    b[:block].call(ServerPluginControl.new(@server))
  rescue Exception => e
    STDERR.puts "WARNING before_thread_start hook failed with exception (#{e.class}) #{e.message}"
  end
end

ThreadPoolの変更

ThreadPoolminmax のアクセサが追加され、外部から値を更新できるようになりました。

attr_accessor :min, :max

同時に pool_capacity の計算ロジックが修正され、負の値にならないよう clamp メソッドで下限が0に設定されています。

変更前:

def pool_capacity
  waiting + (@max - spawned)
end

変更後:

def pool_capacity
  (waiting + (@max - spawned)).clamp(0, Float::INFINITY)
end

これは、@max が動的に縮小された際に spawned が一時的に @max を超える状況で、計算結果が負になることを防ぐための防御的な変更です。

設計判断

ThreadPoolの内部状態を直接変更する方式 が採用されました。

PRの説明では「少し怖いかもしれないが、動的更新とはそういうものなので問題ないと考えた」と述べられています。既存のスレッド管理ロジックが @min@max を定期的に参照する設計になっているため、値を更新するだけで既存のスレッド生成・削減機能がそのまま機能します。

新たなスレッド管理ロジックを追加するのではなく、既存の仕組みを活用することで、変更を100行以内に抑えつつ機能を実現しています。一方で、with_mutex によるロック保護を導入することで、並行更新時の整合性を確保する配慮がされています。

まとめ

本PRは、Pumaのスレッドプール設定を稼働中に変更できるAPIを追加した変更です。既存のスレッド管理ロジックを活用し、最小限の変更で動的調整機能の基盤を提供しています。プラグイン向けの制御インターフェースを分離することで、将来的な負荷適応型スレッド管理の実装への道を開いています。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)の3部構成が明確に守られており、非常に分かりやすい構成です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```言語:ファイルパス)とPR番号のリンク記法([#3658](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Pumaの内部実装に関する内容であり、専門知識を持つエンジニアを対象読者として適切に設定しています。過度な説明がなく、簡潔です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まっています。1段落1トピックの原則も守られており、可読性が高いです。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているすべてのコードブロックは、提供されたDiff情報と正確に一致しています。ファイル名も正しく記載されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「スレッドプール」「mutex」「ファサードパターン」などの技術用語が、文脈に沿って正確に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

APIのバリデーション内容や、`pool_capacity`の計算ロジック変更理由など、コード変更に対する技術的な説明は正確かつ論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内の主張はすべてPRのTitle、Description、Checklistの内容で裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#3658)やメソッド名、クラス名などの固有名詞はすべて正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「スレッドプール設定の動的更新APIを追加」は、PRの主題を正確に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事の内容は提供されたPR情報に限定されており、バージョン情報やリリース予定など、PR外の知識の捏造はありません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

PR Descriptionの「we are actively working on」といった表現を「〜に向けて」と正確に反映しており、時間表現の歪曲はありません。