🤔

Redis不要のSolid QueueはSidekiq OSSに勝てるのか?Rails 8で非同期処理を徹底比較

に公開

背景と目的

Rails8.0 ではActive Jobの機能が拡充されたことに加え、これまでの SidekiqResque などに加えて、新たに Solid Queue という選択肢が提示されました。しかしながら、Sidekiq の公式ドキュメントでは以下のような性能差が示唆されています:

  • Active Job 経由と Sidekiq ネイティブ使用で 約1.2倍の差
  • Solid Queue と比較すると 最大15倍の差

果たしてこれらの差は現実にどの程度再現されるのか? また、Solid Queue を使う場合に Sidekiq に並ぶ性能を発揮するにはどのような設定が必要なのか? OSS ライセンスの範囲内で各方式の性能を定量的に検証しました。

実験環境

実験環境としては筆者のPCにてDocker Desktopのコンテナを利用しました。

  • Ruby: 3.3.5
  • Rails: 8.0.2
  • Sidekiq: 8.0.3
  • Redis: 8.0.1
  • PostgreSQL: 17.5
  • mac mini 2018
    • 3.2GHz 6-Core Intel Core i7
    • 64GB 2667MHz DDR4
    • macOS 15.4.1
  • Docker Desktop: 4.41.0
    • CPU: 4 / Memory: 16GB / Swap: 1GB

測定対象

  • Sidekiq: Sidekiq::Job
  • Active Job: Active Job + SidekiqAdapter
  • Solid Queue: Active Job + SolidQueueAdapter

測定シナリオ

測定シナリオとしてはジョブのEnqueueとPerformについてそれぞれ測定します。またEnqueueにおいては逐次処理とバルク処理、Performについてはスレッド数とプロセス数を変化させた場合の違いについても測定します。

Enqueue 編

モード 件数パターン 備考
逐次 100 / 1,000 / 10,000件 perform_async vs perform_later
バルク 100x1 / 100x10 / 100x100 perform_bulk vs perform_all_later

Perform 編

モード 件数 スレッド数 備考
単プロセス 上記同様 5 / 10 各方式共通
複プロセス 上記同様 5 x 2プロセス Solid Queue のみ(Sidekiq OSS 非対応)

計測指標・方法

実行時の指標としてはメモリ使用量、CPU使用率、実行時間についてを下記の基準にて測定します。

指標 測定方法 ツール
メモリ使用量 最大RSS(常駐メモリ) Docker stats
CPU使用率 平均・最大 %CPU Docker stats
実行時間 enqueue ~ 完了の経過時間 time

測定結果

それでは実際の測定結果を見ていきましょう。

📎 ソースコード・検証用スクリプトは naoto-k/sidekiq-memory-test にて公開しています。

Enqueue

1件ずつ投入

メモリ使用量

件数 Sidekiq Active Job Solid Queue
100 90.06MB 91.59MB 200.6MB
1,000 88.08MB 92.05MB 201.6MB
10,000 88.75MB 91.85MB 203.7MB

CPU使用率

件数 Sidekiq Active Job Solid Queue
100 N/A N/A 72.57%
1,000 N/A 72.59% 76.34%
10,000 65.31% 73.22% 77.41%

実行時間

件数 Sidekiq Active Job Solid Queue
100 0.06s 0.32s 1.81s
1,000 0.37s 1.96s 15.99s
10,000 2.47s 17.3s 2m 34.16s

考察

Sidekiqが圧倒的に高速であることが明確に現れた結果となりました。
Active Job経由では約5〜7倍、Solid Queueでは最大で60倍近い実行時間の差が見られました。
これはActive Jobがシリアライズ処理やラップ処理を内部で行うことによるオーバーヘッド、Solid QueueではRDBMSトランザクション制御によるレイテンシの影響が大きいと考えられます。
メモリ・CPUの消費はSolid Queueがやや高めで、パフォーマンスの代償としてシステムリソースを多く消費している様子が見て取れます。

バルク投入

メモリ使用量

件数 Sidekiq Active Job Solid Queue
100x1 91.75MB 94.49MB 208.4MB
100x10 92.66MB 95.04MB 210.8MB
100x100 95.37MB 96.43MB 212.5MB

CPU使用率

件数 Sidekiq Active Job Solid Queue
100x1 N/A N/A N/A
100x10 N/A N/A N/A
100x100 N/A N/A 66.43%

実行時間

件数 Sidekiq Active Job Solid Queue
100x1 0.01s 0.01s 0.13s
100x10 0.01s 0.06s 0.59s
100x100 0.12s 0.62s 3.84s

考察

バルク処理においては、Active JobとSidekiqの性能差が大きく縮まり、特に小規模なバルク(100件程度)ではほぼ同等の性能を示しました。
これは1件ずつエンキューする際の処理負荷が amortized(平準化)されるためと考えられます。
一方、Solid Queueはバルクでも処理負荷が高く、PostgreSQLを用いた複数行の INSERT 処理やロックの影響を受けやすいことが要因と思われます。

Perform

5スレッド

メモリ使用量

件数 Sidekiq Active Job Solid Queue
100x1 90.4MB 98.2MB 202.2MB
100x10 90.44MB 99.56MB 207.7MB
100x100 91.6MB 100.2MB 210.6MB

CPU使用率

件数 Sidekiq Active Job Solid Queue
100x1 99.99% 100.04% 105.81 %
100x10 100.49% 101.78% 106.01%
100x100 101.34% 103.22% 110.19%

実行時間

件数 Sidekiq Active Job Solid Queue
100x1 3.59s 6.11s 5.57s
100x10 28.03s 53.98s 48.87s
100x100 4m 13.03s 9m 18.79s 7m 33.98s

考察

この構成ではSidekiqが引き続き優れた実行時間とメモリ効率を示しつつ、Solid QueueがActive Jobを上回る性能を示した点が注目されます。
特に中規模バッチ処理(100x10や100x100)ではSolid QueueがActive Jobよりも安定したスループットを発揮しており、適切な条件下では十分実用的であることが確認できました。
Active Jobについては、やはり非同期処理ラッパーとしての内部処理のオーバーヘッドが効いており、スレッド数が少ないほど相対的に不利になる傾向が見られます。

10スレッド

メモリ使用量

件数 Sidekiq Active Job Solid Queue
100x1 90.99MB 94.92MB 195.4MB
100x10 91.95MB 96.45MB 207.6MB
100x100 93.64MB 96.56MB 212.4MB

CPU使用率

件数 Sidekiq Active Job Solid Queue
100x1 102.72% 103.21% 103.98%
100x10 102.45% 103.3% 109.33%
100x100 103.23% 103.24% 107.07%

実行時間

件数 Sidekiq Active Job Solid Queue
100x1 3.7s 6.56s 5.49s
100x10 29.82s 59.63s 42.38s
100x100 4m 44.26s 9m 40.25s 6m 59.32s

考察

スレッド数を10に増やしたことで、Solid Queueのスループットがさらに向上し、Active Jobとの性能差が一層広がりました。
実行時間ではSidekiqが依然として最速ですが、Solid Queueとの差はわずかに縮まってきています。
CPU使用率はSolid Queueが最も高く、ワーカーリソースをより効率的に活用できていることを示しています。
メモリ使用量は増加していますが、全体としては許容範囲であり、スケール性の高さが評価されます。

5スレッド x 2プロセス / Solid Queueのみ

メモリ使用量

件数 Solid Queue
100x1 255.9MB
100x10 269.8MB
100x100 276.2MB

CPU使用率

件数 Solid Queue
100x1 202.47%
100x10 206.81%
100x100 210.51%

実行時間

件数 Solid Queue
100x1 3.99s
100x10 25.53s
100x100 4m 2.4s

考察

Solid Queueの真価が発揮されるのはこの構成です。
プロセスを分割してワーカーを分散させることで、CPU使用率は200%を超え、単一プロセス構成よりも約1.5倍のスループット向上が見られました。
メモリ使用量は当然ながら倍増しますが、それに見合った処理効率の向上が得られています。
OSS版のSidekiqがマルチプロセス非対応であることを踏まえると、Solid Queueのスケール性は大きなアドバンテージとなり得ます。

まとめ / ベストプラクティス

今回の検証により、性能面ではやはりSidekiqネイティブ利用が最も優れており、圧倒的な速度と軽量性を誇ることが改めて確認されました。
ただしSolid Queueも、スレッド数やプロセス数を適切に調整すれば十分に実用に耐える性能を発揮することがわかりました。
特に新規プロジェクトで Redis を導入せずに構成をシンプルにしたいケースでは、有力な選択肢となります。

Active Job + Sidekiq の構成は、既存のActive Jobベースのコード資産がある場合や、開発者の習熟度を考慮してSidekiqをラップしたい場合に適しており、妥協案として有効です。
一方で、Active Jobが持つ非同期処理のラップ処理やキュー管理の抽象化は、性能面ではオーバーヘッドとなるため、その点を考慮する必要があります。

ユースケース別推奨

ユースケース 推奨構成
高性能・リアルタイム性が求められるサービス Sidekiq(ネイティブ)
小規模〜中規模で構成を簡素にしたい場合 Solid Queue(1プロセスでOK)
Active Jobベースの既存コードがある Active Job + Sidekiq Adapter
高いスケーラビリティが必要なワークロード Solid Queue(マルチプロセス構成)

Rails 8.0 時代における非同期ジョブの選択肢として、Solid Queue は 十分に戦える 存在になってきています。
運用面・構成面も踏まえて、最適な選択をしていきたいですね。

COUNTERWORKS テックブログ

Discussion