Which job schedulers fire on time? We tested ten. のカバー画像

Mike Gorman

smplkit向けに構築したアプリケーションインフラ製品のひとつが、HTTPジョブスケジューラーのSmpl Jobsです。もちろん、競合するジョブスケジューラーと比べて優位に立ちたいと考えていましたが、実際にどの程度優れているのか、特に重要なポイントである「HTTPリクエストを定刻に送信する」という点で気になりました。そこで調査してみることにしました。

参加製品

テストのセットアップ

アイデアはシンプルでした。正時にパブリックエンドポイントへリクエストを送信し、到着した日時を記録します。正時からのミリ秒数(スキュー)が小さいほど、定刻に起動していることになります。

アイデアはシンプルですが、スケジューラーが送信でき、かつ到着時刻を記録・保存できるパブリックエンドポイントを見つけることは簡単ではありませんでした。最終的に求めていたのは、ベンチマークを識別するJSONメッセージをPOSTでき、対象と到着日時を記録できる汎用的なベンチマークホスティングサイトでした。希望通りに動作するものが見つからなかったため、私たちで構築しました。3週間後、smplmark.orgが公開され、テスト対象のスケジューラーからのリクエストを受け付ける準備が整いました。

ベンチマークを作成し、対象を定義した後、各スケジューラーをsmplmarkのmeasurement APIへリクエストを送信するよう設定しました。送信するJSONペイロードにはベンチマーク、実行回、スケジューラーのIDを含めています。smplmarkは各測定値の作成日時を記録し、created_at mod 3600000で算出されるskewメトリクスが、正時からのミリ秒数となります。

すべての参加製品は無料プラン(またはそれに近いプラン)で実行しました。一部は月額約1ドルの請求が発生しましたが、条件を公平に保ち、かつ請求額をゼロに近づけるためです。

smplmark.orgを構築した理由

いくつかの欠点

この手法には、既知の欠点が4つあります。

  1. スキューは1時間でモジュロ演算されるため、正確に60.1分遅れて起動したスケジューラーは、実際には6秒しか遅れていないように見えます。これは特殊なケースで、巻き戻しに抵触する可能性があるのはGitHub Actionsのみですが、遅れ幅は秒単位ではなく大幅にずれています。巻き戻しは逆方向にも作用し、早着したリクエストはほぼ1時間遅れと解釈されます。ただし、巻き戻し付近に到着するのはGitHub Actionsのみであり、その信頼性の低さは明らかで、よく文書化されています
  2. エンドポイントはUS-Eastにあるため、US-Westや欧州で動作するスケジューラーはUS-Eastのスケジューラーが負担しないネットワークコストを支払うことになります。ただし、その差はわずか数ミリ秒であり、最終的にはスケジューラーエンジン自体の性能が支配的です。
  3. smplmark.org自体はCloudflare上で動作しているため、Cloudflare Workersにはホームアドバンテージがある可能性があります。リクエストがCloudflareのネットワーク外に出ない場合があります。
  4. スキューはsmplmarkの時計を信頼しています。smplmarkはCloudflare上で動作し、時計はNTP同期されていますが、独立した検証は行っていません。時計がずれた場合、すべての対象が同じだけシフトします。順位は維持されますが、絶対値は変わります。スケジューラー自身の時計は補正されません。自分の時計が「時間だ」と判断して起動することは、測定対象の一部です。

リーダーボード

現在の状況は以下の通りです。以下の画像は固定されたスナップショットで、引用する数値はグラフの横に残ります。ライブボードは毎時更新されるため、この記事を読む頃には数値が変わっています。GitHub Actionsはスケールが大きすぎるため、他のバーが見えなくなるため、このグラフから除外しています。

スケジューラーごとの中央値スキュー(ミリ秒)のライブ棒グラフ。GitHub Actionsはスケールのため除外。最低から最高に並べ替え済み

7月31日時点の正時からのミリ秒単位の中央値スキュー。ライブボードを開くと最新の数値と手法を確認できます。

数値が示すこと

Posthookが中央値スキュー656 msで最も定刻に近く、次点のRunhooksは749 msでした。QStashとSmpl Jobsは約1.5秒でほぼ互角に並び、その後ろにEasyCron、Google Cloud Scheduler、cron-job.orgが続き、要求時刻から一貫して約4〜8秒以内に起動しています。

スケジューラーごとのスキュー折れ線グラフ。GitHub Actionsはスケールのため除外。最下限に張り付く線がいくつかあり、数秒上にある線も複数、約26,500ミリ秒で水平な線が1本、最後の数時間で約51,000ミリ秒へジャンプする線がもう1本ある

7月31日朝までの4日間の到着データ(到着ごとに1ポイント)。GitHub Actionsはスケールのため除外。

興味深いことに、AWS EventBridgeはほぼ正確に26.5秒遅れて到着します。記録したすべての到着は数百ミリ秒の幅の帯内に収まっており、どれだけ遅れているかを正確に時計合わせできるほどです。公平を期すなら、EventBridgeは大規模にイベントをファンアウトするために存在し、その用途では優れています。

Cloudflare Workersも一貫して遅れており、通常は正時から約33秒後ですが、今週のいくつかの実行では51秒近くまでずれました。リクエストが自社ネットワークから出ない可能性があると考えた参加者でも33秒遅れているため、ホームアドバンテージはありませんでした。

ミリ秒単位のスケジューラースキュー統計表:平均値、中央値、最小値、最大値、p95、p99、実行回数。全スケジューラーを中央値で並べ替え

7月31日時点のボード上の全参加者(GitHub Actions含む)の最小値、最大値、パーセンタイル。単位は依然としてミリ秒です。

GitHub Actionsの中央値スキューは約27分ですが、これは控えめな数字です。半分以上の確率でGitHub Actionsは起動すらしていません。公平を期すなら、GitHubはこれを明記しています。スケジュールされたワークフローはベストエフォートで文書化されており、負荷が高いと遅延またはドロップされます。彼らの言う通りです。私たちの言葉を信じなくても構いません。使用しているワークフローは公開されており(https://github.com/smplkit/benchmarks/actions/workflows/cron-skew.yml)、GitHub自身の実行記録はActionsタブにあり、実行が一切発生しなかった時間ごとのギャップも確認できます。

私たちは1位ではない — それでも問題ない

自社スケジューラーの数値が一貫して約1.5秒遅れていることがわかったとき、どこを最適化できるかコードを分析しました。少し早めに起動するアイデアを試しました。一貫して1.5秒遅れているなら、1.4秒早く開始すればよいのではないか。しかし、常に1.5秒遅れているわけではありません。「早めに開始」戦略では、数ミリ秒早く起動してしまうことがあり、それは1.5秒遅れるよりも悪い可能性があると考えました。そこで早期開始を撤回し、結果を受け入れることにしました。数値の改善は続けますが、現時点ではPosthookの最悪実行でも私たちの最悪実行を上回る程度なので、それほど悪くはありません。

私たちの言葉を鵜呑みにしないでください

わかっています。smplkitが作成したベンチマーク、smplkitが作成したウェブサイトでホストされた結果、そしてSmpl Jobsが最も「定刻に」起動するジョブスケジューラーの上位に位置づけられる。これはどう見ても出来過ぎです。だからこそ私たちはsmplmark.orgを作成しました。世界中の誰でもアカウントを作成し、私たちと同じことを実行できます。サポートが必要な場合は[email protected]までメールしてください。

気にするべきか?

要求時刻から数秒以内に起動するジョブスケジューラーは、ほとんどのチームにとって十分実用的でしょう。テストした10個のうち9個は要求時刻から60秒以内に起動し、7個は10秒以内に着地します。ただし、最も定刻な実行を求めるなら、Posthook、Runhooks、Smpl Jobs、QStashはすべて要求時刻から数秒以内に着地します。

しかし「秒単位で起動する」ことは考慮すべき点のひとつに過ぎません。レスポンスの取得、実行履歴、タイムゾーン、リトライポリシー、SDKなどを重視する場合は、2026年のベストcronジョブサービスをご確認ください。