ISUCON8にDMZという名前で参加した。 名前の由来は、参加メンバーの頭文字3つ。 ちょうど、非武装地帯(DMZ)になってゴロが良くて気に入っていたw 結果は予選敗退。。 やはり、壁は厚いなと思いつつも、参加して3年目でついに1万点の壁を突破したので嬉しかった!*1
やったこと
午前中〜お昼くらいまで、ベンチマークを走らせてもほとんどfailedしてしまって全然スコアが出なかった。。 ベンチマークが感想しないと、ログがでないのでどこがボトルネックかわらかないのでこれを最初に解決した。 初期ではアプリケーションとDBが1つのサーバに乗っていたので、これをわけることにした。 これで、10回に1回しか成功してなかったベンチマークが5回に1回くらい成功するようになった。
次にアプリケーションの見直しを行った。 ぱっとソースを読んだ感じ、get_eventsが遅そうだということでこの部分を見直し。 また、reservationテーブルやsheetsテーブルにインデックスを追加。 そして、get_eventsから呼び出されていて、かつ、様々なところから呼び出されていたget_eventも見直した。
get_eventは見たまんまN+1でどうにかするしかないなっと思ったのだが、どうしたら解決するか全くわからなかった。。 仕方ないので、出力するデータをホワイトボードに書き出し、何が必要でどういうデータが入っているかを把握することにした。 実際に書き出してみると行っていることは単純で、かつ、sheetsテーブルは必要がなかった*2ので、シュッと書き直した。 これらの変更によりスコアが3500点くらいになった。
次に私は、 /api/user/:id
を見直すことにした(この時点でだんだん疲れてきていて、他のメンバーが何やっていたかうろ覚え…)。
get_events/get_eventの見直し後にベンチマークを走らせたところ、このURLへのアクセスが遅いと書かれていたというのが理由。
/api/user/:id
は、ユーザが直近で予約した席とイベント情報を表示するためのJSONを返す。
内部では、get_eventを呼び出して席の予約情報を取得しているのだが、一番重い処理である各シートランクごとの予約情報(event['sheets'][:rank]['details']
)を使っていなかったので、これを固定値で書き直して、get_eventを叩かないようにした。
また、直近のイベント情報は直近の席情報に含まれるイベント情報と差異がなかったので、event_idをキーにしてuniqしたArrayを返すようにした。
これで、12000点くらいになった。
ここらへんで16時くらい。
もうあまり時間がないので、シュッとできる点数が上がりそうなことをやることにした。
最初に、セッションをredisに保存するようにした。
このredisは、3台あるサーバの中で唯一何もしていないサーバに配置した。
また、アプリケーションサーバを2台のサーバで実行するようにした。
フロントはh2oのままで、重い処理である /admin
配下の処理をわけるようにした。
最初はredisを載せている側で、/admin
配下を処理していたのだが、こちらはやたらメモリを食う処理があったので、変更した。
最終的には以下のような感じ。
- h20 + アプリケーション(
/initialize
と/admin/
配下) - DB
- redis + アプリケーション(1以外のすべての処理)
この分離を行ってベンチを取ったら18000点くらいになって、ktkr!!!!っとなったので一旦リブートしベンチをとることにした。
そうしたら、failしてしまった。。。
原因は、アプリケーションをわけてせいで /admin/api/reports/sales
というめちゃくちゃ重い処理がロックを取れずに500エラーを返すことだった。
もう残り時間も少なくシュッと解決できなかったので、begin〜resuceで処理を囲み成功するまでSELECTする作戦で回避した。。
競技終了前に再度リブートをかけ、ベンチを取ったところ 19045点だった。
感想
今まで、インフラレイヤ担当として参加していたが、今年はアプリケーション担当としてコード変更をメインに作業した。 これが結果として功を奏したのかもしれない。 私がインフラ担当だったら、まずh2oをNginxにして、mariadbをMySQLにして…みたいなことを考えていたと思う。 今年はそこをきっぱり諦め、まずアプリケーションを治すところに専念したのが良かったのかもしれない。
また、インフラ担当とはいえアプリケーションコードを理解するのは大切だと改めて思った。 これはISUCONに限らず実務でもそうで、アプリケーションコードを把握していないと、どこがボトルネックか?どこで障害が起こっているか?などすぐに出てこない。 開発担当に聞くのもありだけど、インフラ側がその部分を修正できるとよりDevOpsっぽくなるのかなぁっと思った次第。