TT Lab
はじめる
学ぶ 学習パス コース

デバッグ実戦

やり直せば通る問題 — 何回回せば直ったと言えるか

TT Labで続きを見る

目標

間欠的な失敗の発生率を試行で測り、推定値に区間を付けます。失敗した実行でだけ真になる条件を試行の記録から抜き出し、間隔をあけて測り直して、観測が症状を消すことを確認します。最後に、直したと言うには何回実行すべきかを計算し、その回数を実際に実行して証明します。

なぜ重要なのか

「もう一度やったら動きました」は、調査を終える文のように聞こえますが、実はデータ2件です。1回失敗し、1回成功しました。ここですべきことは、もっと実行して分数を作ることです。 間欠的な失敗が危険な理由は、直ったかどうかを1回の成功で判断させてしまうからです。失敗率10%の問題を直さないまま1回実行して合格する確率は、90%です。そのため、「何回連続で合格させるべきか」を先に計算する必要があります。 このラボで難しいのは、ループではなく判定の根拠です。試行回数なしで比率だけを書くと、20回中2回と200回中20回を区別できず、失敗した実行の証拠をその場で残さなければ、あとから尋ねる相手がいません。 採点ツールは、ランダムさに左右されません。採点ツールが作った決定的なターゲット(ちょうど5回に1回失敗するコマンド)にあなたのツールを実行して数字を照合し、あなたが残した記録と計算は、採点ツールが同じ公式で再計算して突き合わせます。

ステップ

  1. /root/flaky/gen_flaky.pyを作成して実行し、/root/flaky/job.pyを作ってください。
  2. /root/flaky/measure.pyでjob.pyを200回以上実行し、/root/flaky/rate.jsonに失敗率とウィルソン区間を書いてください。
  3. /root/flaky/plan.pyを作り、/root/flaky/runs_needed.jsonに、信頼水準ごとに必要な連続合格回数を求めてください。
  4. /root/flaky/collect.pyで試行ごとに証拠を残し、/root/flaky/facts.jsonlを作ってください。失敗するときだけ真になるものは、/root/flaky/only_when_fail.jsonに書いてください。
  5. 試行の間隔をあけて測り直し、/root/flaky/observer.jsonに、2つの測定を並べて書いてください。
  6. /root/flaky/policy.jsonに、リトライバジェットと隔離の基準、グリーン判定に必要な連続合格回数を、計算で決めて書いてください。
  7. 修正バージョンを、計算された回数だけ実行して、/root/flaky/proof.jsonに証拠を残してください。
  8. /root/flaky/summary.jsonを作り、/root/flaky/flaky_report.mdに4つの節で報告してください。

参考

間欠的に失敗するジョブを手に入れる

/root/flaky/gen_flaky.pyを作成して実行し、/root/flaky/job.pyを作ってください。そのあと、job.pyを手で何回か実行して、成功したり失敗したりするのを自分で見てください。

このスクリプトをそのまま保存して実行すれば構いません。できたjob.pyを連続で10回ほど実行してみてください。終了コードが0の実行と3の実行が混ざって出ます。何回に1回なのかは、まだ数えないでください。それがステップ2です。

「たまに」を分数に変える

/root/flaky/measure.pyを作成して、job.pyを200回以上実行し、/root/flaky/rate.jsonにcommand・trials・failures・rate・ci_low・ci_high・gap_msを書いてください。区間は、95%のウィルソンスコア区間です。

失敗は、終了コードが0でないものとして数えます。比率だけを書くと、20回中2回と200回中20回を区別できないので、試行回数を一緒に残してください。ウィルソン区間の2つの式は、参考の節にあります。失敗が0件でも幅が0にならないのが、この区間を使う理由です。

何回実行すれば直したと言えるか

/root/flaky/plan.pyを作成し、/root/flaky/runs_needed.jsonに、observed_rateと、信頼水準0.9・0.95・0.99それぞれのrunsを含むtable、そしてchosen(0.95)を書いてください。

直さないままn回すべて合格する確率は、(1-p)のn乗です。その確率を1-c以下に抑える最小のnが答えで、対数を取れば1行で出ます。切り上げを忘れないでください。小数回は実行できません。

失敗したその場で証拠を残す

/root/flaky/collect.pyで60回以上実行し、/root/flaky/facts.jsonlを作ってください。/root/flaky/only_when_fail.jsonには、trials・failures・exit_codes_on_failure・exit_codes_on_success・token・failure_trialsを書いてください。tokenは、すべての失敗の標準エラー出力にあって、どの成功にもない単語です。

間欠的な失敗は、もう一度呼び出せません。試行ごとに終了コードと標準エラー出力をその行に書いておいて初めて、あとから尋ねる相手ができます。tokenは、失敗の記録を目で眺めればすぐに見えます。大文字の1つの単語です。成功の記録にその単語がなければ、tokenになります。

観測が症状を消す

試行の間隔を2000ミリ秒以上あけて20回以上測り直し、/root/flaky/observer.jsonにfastとslowの2つの測定(trials・failures・rate・gap_ms)とchangedを書いてください。遅く測ると、失敗が0件になる必要があります。

ログを付けて1ステップずつ実行すると、症状が消えることがよくあります。タイミングに依存する条件が、遅くなった瞬間に成立しなくなるからです。消えたという事実自体が手がかりです。原因が速度か順序にあるという意味だからです。measure.pyの--gap-msで、同じ状況を作れます。

リトライバジェットと隔離の基準を計算する

/root/flaky/policy.jsonにobserved_rate・confidence(0.95)・green_runs_required・retry_budget・quarantine_afterを書いてください。retry_budgetはp^(r+1) <= 0.01を満たす最小のrで、quarantine_afterは1以上の整数です。

リトライは間違った対応ではありませんが、回数には根拠が必要です。失敗率がわかれば「すべて失敗する確率」を計算でき、そこからバジェットが出ます。隔離しないと、人々は失敗を無視する習慣を身につけ、その習慣は本物の失敗にも適用されます。

直したことを根拠とともに主張する

修正バージョン(--fixed)を、ステップ3で計算した回数以上実行して、/root/flaky/proof.jsonにcommand・required・trials・failuresを書いてください。failuresは0で、trialsはrequired以上である必要があります。

1回合格したことは証拠ではありません。失敗率pの問題を直さないまま合格する確率が、すでに1-pだからです。ステップ3のchosen.runsをそのまま持ってきて、その回数だけ実行し、その記録をファイルに残してください。採点ツールは、同じコマンドを自分でもう一度実行してみます。

確率を1枚で報告する

/root/flaky/summary.jsonにtrials・failures・rate・ci_low・ci_high・token・green_runs_required・proof_trials・observer_changedを書き、/root/flaky/flaky_report.mdに## 얼마나 자주인가、## 실패할 때만 참인 것、## 관측이 바꾼 것、## 고쳤다고 말하려면(韓国語の見出しは、順に「どのくらいの頻度か」「失敗するときだけ真になるもの」「観測が変えたもの」「直したと言うには」という意味です)の4つの節で報告してください。

報告書の価値は、結論ではなく数字にあります。試行回数と失敗回数、区間、必要な連続合格回数を、すべて書いてください。観測を付けたときに消えたという事実も手がかりなので、一緒に書きます。