連載「クリシンクエストをつくる」· 第4編/全8編
8秒が0.3秒になった、たった1行の設定 — 速さの正体は「距離」だった
同じコード、同じデータベース。なのに本番だけ激遅。犯人は地球の裏側にいました
本番に出したクリシンクエストが、なぜか異常に遅い。同じコード・同じデータベースなのに表示に8秒以上。原因を追うと、アプリとデータベースが太平洋をはさんで離れていました——速さの正体は「距離」だったという、たった1行で30倍速くなったお話です。
連載「クリシンクエストをつくる」· 第4編/全8編
同じコード、同じデータベース。なのに本番だけ激遅。犯人は地球の裏側にいました
本番に出したクリシンクエストが、なぜか異常に遅い。同じコード・同じデータベースなのに表示に8秒以上。原因を追うと、アプリとデータベースが太平洋をはさんで離れていました——速さの正体は「距離」だったという、たった1行で30倍速くなったお話です。
前回、クリシンクエストを Vercel と Supabase の本番環境に引っ越したお話を書きました。無事に「届く」状態になった——と思った矢先、奇妙なことが起きたんです。
本番が、やたら遅い。
自分のPCでは一瞬で出る画面が、本番ではなかなか出てこない。とくに「成長レポート」のような、データをたくさん集める画面がひどくて、表示まで、ときに8秒以上かかってしまう。同じコードで、同じデータベースのはずなのに、なぜローカルと本番でこんなに違うのでしょうか。あなたも、手元では速かったものが本番で急に遅くなって、頭をかかえたこと、ありませんか。
最初は理由がさっぱり分かりませんでした。けれど、ここで焦って勘で直しはじめると、たいてい遠回りになってしまうんですよね。まずやるべきは、推測ではなく計測です。
どの処理に時間がかかっているのかを測ってみると、犯人はすぐに絞れました。データベースへの問い合わせです。一回あたりは小さいのに、画面を1枚出すたびに、その問い合わせが何十回も積み重なって、全体で数秒に膨らんでいました。
ここで引っかかりました。同じ問い合わせを、ローカルでやれば一瞬なのに。本番だと、一回ずつがやけに遅い。処理の中身は同じなのに、です。
こういうとき、つい「コードのどこかが悪いはずだ」と思い込んでしまいませんか。私も最初はそう疑って、問い合わせの中身を何度も読み返しました。でも、何度見てもおかしなところは見つからない。コードが同じなら、犯人はコードの外にいるはずです。そう発想を切り替えたところから、ようやく霧が晴れていきました。
違うのは「中身」ではなく「場所」でした。
調べていくと、こういう状況でした。
つまり、アプリがデータを一回問い合わせるたびに、その信号が太平洋を往復していたんですね。東京とアメリカ西海岸は、光の速さでも片道で数十ミリ秒かかります。往復すれば、それだけで0.1〜0.2秒。一回なら気にならないのですが——。
ここで効いてくるのが、さっきの「画面1枚で何十回」という事実です。
一回0.1〜0.2秒の往復でも、それを順番に何十回もくり返せば、合計は数秒になってしまいます。これが8秒の正体でした。
海外通販を思い浮かべてみてください。必要な部品を、まとめてではなく1個注文しては届くのを待ち、また1個注文しては待つ——を30回くり返したら、どうなるでしょうか。一個あたりの送料や日数はたいしたことなくても、積み上がれば途方もない時間になりますよね。近所の店で同じ30個を買えば、ほんの一瞬なのに。
本番のアプリは、まさにこれをやっていました。遠くのデータベースに、何十回も“往復のおつかい”を頼んでいたわけです。中身(コード)の問題ではなく、アプリとデータが住んでいる場所が遠かった。これが、ローカルでは速くて本番では遅い理由でした。ローカルでは、アプリもデータも同じ1台の中にいたのですから。
ここで一つ、見落としやすい落とし穴があります。一回あたりの遅れは、本当にわずかなんですね。だから、テストで一回だけ問い合わせて測ると、「ちょっと遅いかな?」くらいにしか見えません。問題が牙をむくのは、その「ちょっと」が何十回も連なったときです。小さな遅れほど油断しやすく、積み上がってから初めて姿を現す——パフォーマンスの悩みって、たいていこういう顔をしている気がします。あなたのアプリにも、こっそり往復をくり返している場所、ないでしょうか。
原因が「距離」だと分かれば、答えはシンプルです。アプリとデータベースを、同じ街に住まわせればいい。
設定ファイルに、「このアプリの処理は東京で動かす」と一行書き加えます。それだけで、アプリ本体がデータベースと同じ東京で動くようになりました。往復していた信号は、もう海を渡りません。同じ街の中の、ご近所づきあいになったわけです。
(あわせて、複数の問い合わせを少し並行して扱えるよう、接続まわりも軽く調整しました。とはいえ、効果の大半は「場所をそろえた」ことによるものです。)
おもしろいのは、この一行が「何かを足した」わけではない、というところです。新しい仕組みを作ったわけでも、難しい工夫を凝らしたわけでもありません。ただ、すでにあったものの置き場所をそろえただけ。それでこれだけ変わるのですから、土台の配置がいかに大事か、身にしみて感じた瞬間でした。
直したあとに測り直すと——
体感で言えば、「待たされるアプリ」から「すぐ出るアプリ」へ。約30倍です。コードのロジックは一文字も変えていません。変えたのは、アプリが動く場所だけでした。
数字で見ると、ちょっと不思議な気持ちになりませんか。あれだけ悩んだ8秒が、一行の設定で0.3秒になる。プログラムをうんと賢くしたわけでも、データを減らしたわけでもないのに、です。遅さの原因が「場所」だったからこそ、場所を直せば、それだけでまるごと解消した。問題の正体を取り違えていなければ、直し方はこんなにも軽くて済むんですね。
この一件で、深く納得したことがあります。速さの正体は、しばしば賢さではなく距離だ、ということです。どれだけ処理を工夫しても、遠くと何度もやり取りしていれば遅い。逆に、近くに置くだけで、何もせずに速くなる。
そして大事なのは、これを勘ではなく計測で突き止めたことです。今回はたまたま直し方が一行で済みましたが、いつもそんなに簡単とは限りません。それでも、「なんとなく遅い」を「どこが、なぜ遅い」に言い直せれば、少なくとも何を直すべきかは見えてきます。問題を正しく言い直せた時点で、半分は解けている——これは前に書いた「問い直す力」のお話とも、どこかでつながっている気がします。
この犯人探しでも、役割ははっきりしていました。実際に計測し、ログを並べ、設定を書き換えたのはAIです。私がやったのは「なぜ本番だけ遅い?」と問い、上がってきた数字を読んで「これは距離だ」と筋を見抜くこと。手を動かすのはAI、問いを立てて見立てるのが私。コードを書く速さでは、もうAIに敵いません。だからこそ人間に残るのは、正しい問いを立てる力なのだと思います。それはくしくも、このゲームが育てようとしているものと同じなんですね。もしあなたが「なんとなく遅い」に出くわしたら、まず勘で直す前に、一度だけ測ってみませんか。
次回は、ログインのしくみ——自前の認証をやめて、学習者・企業担当者・運営者で入口を分けたお話を書きます。一緒に見ていきましょう。
— クリシンクエスト開発記・第4回