isucon9予選2日目に参加してきました


isucon9予選2日目にチーム流れ弾として参加し、予選通過できました。

@Konboi、@tkuchiki、毎年チームを組んでくれてありがとう。

チームメンバーの記事

事前準備

予選当日までにやった事としては

  • ISUCON8予選問題をGoで復習
  • 1度3人で集まって作戦会議
  • ISUCON8予選問題をRubyで復習

をしました。

Konboi、tkuchikiが2人ともGoに慣れていることもあり、ここ最近のisuconではGoを選択することが多いです。

そのため最初はGoで過去問の復習をやっていたのですが、自分は普段Rubyを書くことが多くGoはisuconの時くらいしか使っていないため、ちょっとしたコード改修をするにも時間がかかってしまうのが悩みでした。

作戦会議の時にそんな悩みを相談したところ「GoとRuby両方のアプリを動かして必要に応じてnginxでproxyするようにするので大丈夫」とアドバイスもらい自分はRubyで進めることにしました。

当日やったこと

インフラ周りはtkuchikiにまるっとお願いして、自分はKonboiと一緒にアプリケーションの改善を進めました。

  • マニュアルを読む
  • APIドキュメントを読む
  • rubyアプリのローカル環境を構築
  • ループ内でseller_idからユーザ情報を取得している部分を、WHERE id IN (user_ids)で一括取得するように変更しN+1を解消
  • initialize時にcategory情報をキャッシュし、キャッシュから返すように変更

この辺ですでにお昼過ぎになっていました。

tkuchikiにGoとRubyが動く状態にしてもらったのですが、category情報は色々な場所から呼ばれているため結局GoにもRubyにも同じ改修が必要になって効率が悪いということに気づき、Konboiに改修内容をサクッとGoに移植してもらい、以降はGoに統一することにしました。

自分はRubyのコードを読んで改修できそうな箇所を見つけ、KonboiとペアプロをしながらGoのコードを改修してもらうというやり方で進めました。

  • shipment serviceの呼び出し処理を減らす

ベンチを回すと/buyで500エラーが出ており、ログを見ると外部APIのshipment serviceがエラーになっていました。

shipment serviceのドキュメントを見ても/statusに複数ID指定が可能というようなことは書かれていなかったので、shipment serviceは意図的に貧弱なサーバになっているのではないかと仮定しました。

その仮定の元、shipment serviceを呼び出しているコードを調べていくと/users/transactions.jsonの中ではshipment serviceの呼び出しが必要ないことに気づき、配送ステータステーブルから情報を取得するように変更しました。

  • アプリが真っ白になる問題の解消

ベンチは通るものの、ページを開くと真っ白画面しか表示されない現象が発生したので調査。

ローカルのファイルをそのままデプロイしている影響で、シンボリックリンクの向き先が別の場所を指しているのが原因でした。

tkuchikiにdeploy scriptを修正してもらい無事解決。

  • /buyでのuserのlockを削除

for updateが書かれていましたが、user情報をupdateしていなかったので不要と判断して削除するようにしました。

振り返り

とりあえずできることをやっていこうということで少しずつ改善を進めていたものの、17時30分ギリギリまでスコアがあまり伸びず、常に焦ってバタバタしている状態になっていました。

app serverが複数台になったタイミングでスコアが跳ねてやったーとなったものの、17:50に再起動試験をしたらアプリが立ち上がらずみんな大慌てでした。

最後の数分でtkuchikiが起動スクリプトに手を加えてくれたおかげで何とか無事に追試が通り本当によかったです。

本戦でもきっと焦るに違いないのですが、なるべく落ち着いて臨もうと思います。

さいごに

運営の皆様ありがとうございました。

フロントもサーバもしっかり作り込まれておりとても濃い時間を過ごすことができました。

本戦もよろしくお願いいたします。