ishikawa_pro's memorandum

若手webエンジニアの備忘録です.

Swift Node.js Docker AWS etc...色々やります。

ISUCON11 予選に参加しました

こんにちは。
ブログ更新がすごく久しぶりになってしまいました。
ISUCON11 予選に参加したので、今年も出場レポートを残しておきます。

isucon.net

自分の実力とか成長を確かめるために、今年も1人チームでの参加にしました。

使った言語

普段業務では、Node.js や TypeScript でサーバーを書いてるので、Node.js (TypeScript) 実装で挑戦しました。
フレームワークは定番の Express.js だったので、特に心理的障壁などもなくコード自体は読むことができました。

やったこと

来年の自分用に、やったことをまとめておきます。
初期スコアをちゃんと記録してなかったのでかなり曖昧ですが、Node.js 実装だと 1000点 ちょっとくらいでした。
Go言語実装の方が、結構初期スコア高かったような気がしました。

リポジトリ作成など

ソースコード管理のため、GitHubのプライベートリポジトリにコードをpushしました。

github.com

コードの編集は、ローカル環境に clone して作業しました。
やったことを記録しておくために、一応作業内容単位でブランチを切って、プルリクエストを作成して進めました。
1人でやるので、CI/CD環境とかは作成してもそんなにうまみはないかなと思って特に構築しませんでした。

構成確認・ログ周りの設定

コードを読んだりする前に、アプリケーションの構成を確認してログの設定などをしました。
構成は、 Nginx + サーバーアプリ + MySQL(mariaDB) でした。
ログ周りの設定は、初めに Nginx のログフォーマットを修正してalp で解析できるようにしました。
github.com この作業は、事前に復習してて手元に作業手順を用意してたので、10分くらいで終わったと思います。
次に DB が MySQL だったので、slow query log を吐くように設定して、pt-query-digest で解析できるようにしました。

www.percona.com

これは手順書とか用意してなかったですが、15分くらいで終わったと思います。

isu_condition のINSERTを改善

alp でアクセスログを見ると、[post] /api/condition/:jia_isu_uuid のリクエストが多かったので、とりあえずそこのコードを確認しました。
1リクエストで複数の isu_condition をINSERTする際に、for文で1行ずつ INSERT をしていたので、1クエリで複数行INSERTできるようにSQLと実装を改善しました。

github.com

この改善で、スコアが 2809 まで上がりました。

isucondition テーブルにindexを貼る

次に確か、slow query log などを見てました。
isu_condtionを jia_isu_uuid で引いてるところがあり、EXPLAIN で実行計画を見たらテーブルスキャンしてそうだったので、インデックスを貼りました。
結果をちゃんとメモってなかったんですが、これは結構効果があり、スコアが9000前半くらいまでは上がりました。
確かここまででやって、13:30 くらいだったような。

isu_condtion の INSERTを改善(その2)

次にまた、 [post] /api/condition/:jia_isu_uuid の改善をしました。
レギュレーションによると、

POST /api/condition/:jia_isu_uuid で受け取ったコンディションの反映が遅れることをベンチマーカーは許容しています。

とのことだったので、 insert のクエリを投げた後に、 await で結果を待たないでレスポンスを返してしまうように実装を修正しました。
github.com これもそれなりに効果があり、スコアが 10204 になりました。
ここらへんまでで 14:00 過ぎくらいだったはずです。
順位は100位手前くらいだったような気がします。
お腹が空いたのでここら辺で一旦休憩しました。

DBの調整

去年の自分の参加ブログを確認して、thred_cache_size, query_cache_size, innodb_buffer_pool_size などを調整していたので、今回も値を調整してみました。
ISUCON10 予選に参加しました - ishikawa_pro's memorandum
これで、スコアが max 11000 くらいまで上がったはずです。(記録残してなかった。。)

その他もろもろ

前日の仕事の疲れが出てしまい、後半からかなり集中力が切れてしまいました。。

データの取得時にトランザクション貼ってるところが何箇所かあったので、一旦外してパフォーマンス見てもいいのではと、なんとなく思って、試したりとかしてました。
graph取得のトランザクション削除 by ishikawa-pro · Pull Request #3 · ishikawa-pro/isucon11-qualifying · GitHub
あんまり効果なかったです。

最後に isu の一覧取得で、 isuに紐付くisu_conditionのデータをfor 文を使ってシリアルに取得していたので、 Promise.all でパラレルに取得するようにしました。
github.com これもパフォーマンス的には変わらなかったです。
そもそも N+1 なので、SQLでJOINして1クエリで取得できるようにすべきだと思ったんですが、時間がなかったので無理でした。

最終的にDBのチューニングでは、値をいじりすぎたりして、ちょっとスコアを落としてしまい、9000点後半代でフィニッシュ。

振り返り

去年と比べると、自分が去年やれたことは、お昼過ぎくらいにはこなしててよかったです。ただ、そこからさらに改善するところまで持っていくことができなかったのが後悔です。
DB周りは、Indexを貼ったりなどをもっと積極的に試行錯誤してもよかったなと後になって思いました。
普段の業務でMongoDBを使ってて、SQLを全く書いてないのもあり、SQLの改善などに手を出せなかったので、なんとか来年までにSQLRDBも勉強する時間を作りたいなと思いました。
あと、いまだに3つのインスタンスを活かすところまで改善ができないので、そういうインフラとかの設定周りも勉強して伸ばしていきたいです。

来年もISUCONがあるかはまだ分からないですが、来年に向けて技術を高めていこうと思います!
運営や他の参加者の皆様、お疲れ様でした!!