ISUCON11予選に参加した

ぼっちなので一人参加です。

参加は今回で2回目。

なんの下準備もせずに挑んだ&一人だったので、作業はローカルでは一切行わず、sshした先でずっと作業してました。

起床が9:30とぎりぎりだったため、実は協議終了までほとんど何も食べなかったという苛酷な感じでした。

 やったことを適当にならべる

競技開始後、とりあえずまずはベンチを走らせつつドキュメント読んで、nginx log と アプリケーションログを見つつ MariaDBのslow log を取得して sql 実行回数を見るとかしてました。

goの実装、DBアクセスが全部生クエリだったので SELECTでサーチして、 必要そうなindexを sql/0_schema.sql に書く というのをまずやりました。

N+1のおかげで大量に実行されているのがあったので、N+1解除すれば速くなるかな?とやってましたが、結局 アクセスが大量に来るタイミングでその1クエリが1sec超えるのでダメだなぁという感じになりました。

振り返ってみると、N+1を解除したらめちゃくちゃ速くなるという性質のクエリではなかったように思います。

DBのチューニングは、バッファサイズ調整とかくらいです。 DBのCPU使用率が100%はりついていたので、どうしたらいいんだろうなぁ?と思いつつ。 これもあとで binlog 出力やめたりするとよい、というのを見ました。

nginx は、 /assets/ のstatic file hosting を 行うようにしてます。アプリとnginxは全然メモリ使ってなかったので、 request buffer とか response buffer を大きくして一時ファイル書き出しをしないようにもしてます。

あとは、 マニュアルにinsert 結果が1sec以内に反映されれば遅延してもいいと書いてあったので /api/trend を nginx で1secキャッシュしたら、ベンチマークが容赦なくデータが古すぎです。と出力するようになりましたが、それでも timeoiutだらけよりはスコアがあがったので、結局 キャッシュし続けました。

あとは、データの 挿入処理のところに // TODO: 一定割合リクエストを落としてしのぐようにしたが、本来は全量さばけるようにすべき と書いてあったので、修正すべくbulk insert するようにしたんですが、数値をいじった(数字を大きくした)ら性能が落ちたのでそれではダメなのかな?とおもって いたんですが、 競技終了後の雑談を読んでいて、不等号を逆に見てしまっていたことに気づきました。

0.9 って、90%は受け付けるとおもうじゃないですか?思わないです?

nginx のキャッシュがらみの設定いじったり、 アプリでうまいことヘッダ追加して conditional get させる。みたいなの、全くやったことがなかったので、その辺のやり方が全然わからず、調べていたら時間がなくなりました。

使ったマシンですが、最終的に DB1台、 nginx+アプリで1台 という感じです。 DBはCPU使い切ってたので、2台つかってSELECTを分散させると速くなったのかもしれないなと思いつつ。 nginx+アプリはだいたい アプリが110%、nginxが60%で 200%使い切ってなさそうなので、分けても性能かわらないだろうなという状態だったので、特に分割は考えませんでした。

考察

総じて、普段からもっと手を動かさないとダメだなという結論にいたりました。

とはいえ、普段会社で触ってるアプリでそんな細かいチューニングが必要になることないんですよね。