isucon10予選に参加しました


ISUCON10予選に参加し予選敗退しました。
今年も @Konboi, @tkuchiki と一緒にチーム流れ弾として参加しました。

チームメンバーの記事

事前準備

  • isucon9予選, 本選の復習
  • isucon8予選の復習

今年はNew Relic特別無料ライセンスを使わせてもらうことができたので、過去問にNew Relicを入れて素振りをしました。
ISUCON10 参加チーム限定で New Relic 特別無料ライセンスを提供します。 – New Relic公式ブログ

デフォルト設定だとDBの分析はできないので諦めていたのですが、ウェビナーのNewRelic講座に参加した際に↓のようにすればDB分析ができることが分かりNew Relic大活躍でした。

当日やったこと

例年と変わらずインフラ周りはtkuchikiにまるっとお願いして、自分はKonboiと一緒にアプリケーションのチューニングを進めました。
今年は初のリモートisuconということで、3人でGoogle Meetをつなぎながら競技に臨みました。

普段触っている言語が自分はruby、Konboiはgoなので、101サーバはruby, 103サーバはgoが動くようにしてもらいそれぞれの言語でチューニングを進めました。
tkuchikiがrubyとgoを個別にデプロイできるスクリプトを用意してくれていたおかげで手軽にベンチを試せてよかったです。
最終的にはgoに統一することになり、Konboiの移植負担が増えてしまったのは申し訳なかったです。

  • ローカル環境を素早く作れるようにDockerでmysqlとredisのコンテナを立てておく
  • マニュアルを読む
  • アプリを触る
  • New Relicの導入
    goだと導入が大変なのでrubyにNew Relicを入れて3人で確認。
    newrelic
    searchとnazotteがボトルネックになっており、Konboiがnazotte、自分がsearchを見ることに。
    searchのfeaturesがカンマ区切りで格納されているので、正規化したほうが良さそうと思ったものの重めの改修になりそうなので後回しに。
  • chair stock 0のデータは削除
    insertはあってもupdateはなかったのでstockが0になったデータは削除するようにして、searchの時の在庫チェック(stock > 0)をなくした。
  • low_pricedにindexが効くように
    chair, estateそれぞれのlow_pricedもボトルネックになっていたのでindexを追加。
    これでスコア伸びるかと思ったがベンチの結果はほとんど変わらず焦る。
  • searchのfeaturesの正規化
    chairとestateそれぞれに(chair|estate)_feature_master, (chair|estate)_featureテーブルを追加し、初期データからinsert文を書き出すスクリプトを作成。
    機能の条件検索はORではなくANDなので自己結合のSQLを書いて対応したが、思った以上に対応に時間がかかってしまった。
    ようやく実装ができたのでベンチをかけてみたもののスコアはほとんど変わらず。
  • recommended_estateのクエリ調整
    幅、高さ、奥行のうち最小の2つを使えば6つのORを2つに減らせるので修正。
    ついでにORをUNIONに置き換えた。
    これもベンチの結果、スコアはほとんど変わらず。
    感想戦をやっていて気づいたがUNIONにすると重複を除外する分、mysqlのCPU負荷が増えるためスコアが下がった。

反省点

rubyでの改修をしても終始スコアが伸びず、焦ってしまったのが良くなかった。
当初はチューニングしたendpointごとにgoとrubyを切り替える予定だったが、実際は101サーバはruby、103サーバはgoでベンチを回していたので、rubyはnazotteがボトルネックのままベンチがかかっていたので一向にスコアが伸びなかったのだと今さら気づく。
go側はKonboiが適宜rubyのコードを移植してくれていたのでスコアは少しずつ伸びていったが、rubyからの移植に時間が取られてしまう問題があるので2言語を使っていい感じにチューニングするのは難しい。
やはり自分がgoを覚えるのがチームにとっては一番効率が良いなぁ(と毎年思っていてできていない)。

また、featureの正規化を行ったが、そもそもfeatureに対するアクセスは少なかったようで、ここはきちんとログを分析すべきだったと反省。
総じて基本が疎かになっていた。

感想戦

今年は悔しい結果となったので忘れないうちに感想戦をやることにした。
最近のisuconはDocker環境が用意されているので手軽にローカルで動かせてありがたい。
docker-composeのdeploy項目を設定して、当日の環境(1CPU 2GB Memory)を再現するようにした。

compatibilityオプションを付けてdocker-compose upを実行。

docker-compose --compatibility up
  • mysql8に変更
  • lowprice用のindex追加
  • nazotte n+1をなくしてspatial indexを利用
  • db分割
  • bulk insert
  • search用のindex追加
  • slow-logを止める
  • New Relic外す

をやってスコア2237。

さいごに

運営の皆様、今年もありがとうございました!
いつも一緒に参加してくれるKonboi, tkuchikiもありがとうございます!