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人で確認。
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もありがとうございます!