かきあげせいろはラーメンがたべたい

技術プログラミングいろいろ記録メモ備忘にゃーん!

ISUCON12予選に参加しました!

これです。 isucon.net

毎年盛り上がっているのをTwitterで見つつも、自分はインフラが全然わからなかったのでいままで参加したことはありませんでした。 しかし一昨年ぐらいからインフラをちゃんと勉強していこうと決意していたことと、書籍「達人が教えるWebパフォーマンスチューニング」を読んだことでチャレンジしてみようという気持ちになったので思い切って参加してみました。

gihyo.jp

結果は惨敗でしたが、とても学びが多かったので久しぶりブログに記録します。

知識レベル

  • 普段はJavaでバックエンド、VueやAngularでフロントエンドを書く仕事をしています
  • インフラに触る機会はほぼありませんが、たまにデプロイのためにEC2をつかったノーマルな?インフラを触ることがあります

予選でやったこと

  • 開始と同時に展開されたマニュアルを読みました
  • 画面を一通り見ました
  • 初期状態でベンチマークを実行しました
  • 参考実装をJavaに切り替えました
  • この状態でベンチマークを実行しました
  • ソースコードをGit管理しました(ソースコードがどこにあるかを探すのに結構時間をつかいました。sysytemctlのserviceからたどればよかった…)
  • DBの接続情報をソースコードから探してDBアクセスし、テーブルなどを確認しました
  • mysql --help | grep "Default options" -A 1でDBの設定情報を探し、そこからログファイルの場所も探しました
  • ベンチマークを実行しつつtopをみて、DBのCPU使用率が支配的だったのでDBから着手することにしました
  • スロークエリログの設定をONにしました
  • pt-query-digestをインストールし、visit_historyテーブルに対してのクエリをチューニングすることにしました
  • SELECTで指定されているカラムを狙い複合INDEXを作成しましたcreate index player_id__created_at__idx3 on visit_history(tenant_id, competition_id, player_id, created_at);
  • 実行計画でINDEXが使われていることを確認し、再度ベンチマークを実行しました
  • 再度ベンチマークを実行しつつtopをみて、アプリの方がCPU使用率が高くなったので、alpをインストールしnginxのログフォーマットをalp用に変更しました
  • alpの結果からランキングを取得するエンドポイントが重い事がわかったので、処理内部にストップウォッチを仕込み、一番重そうな箇所を特定しました
  • プレイヤー情報取得部分がN+1になっていたので、処理前に一回のSQLで全取得するようにしました
  • 再度ベンチマークを実行し、スコアが上昇することを確認しました
  • スコアの上昇具合が他のチームと乖離しすぎていることに疑問を抱き始めました
  • 再度マニュアルを読み返したところ、initのエンドポイントがスコアにとてもかかわっていることを認識し、処理の内容を確認しました
  • SQLiteのファイルをのぞいたところ、何をやっているのかよくわからず、しかしファイルの名称からテナント関連の処理をしてそうということだけわかりました
  • SQLiteの改善をあきらめ再度topでDBが重くなっていることを確認し、replaceのクエリを改善することにしました
  • そもそも一意のIDを払い出せればよさそうだったため、JavaでUUIDを生成しSQLは実行しないようにしました
  • 再度ベンチマーク
  • 18:00になったので終了

振り返り

やったことを列挙しましたが、一つ一つのオペレーションに慣れておらず、時間がかかっていました。たとえばスロークエリログを有効にした場面ではログローテートをしたあとに書き込みがされなかったりして、その解決に時間をとられたりなど普段触っていないこと起因のような機動力の遅さをとても感じました。 上記が一番強く感じたことですが、それ以外にも

  • 全体を俯瞰する能力がなさすぎる(nginxのことをしばらく忘れてた)
  • ソースコードを見つけるのに時間がかかった(セオリーを知らない)
  • Gitを活用出来ていない(一人チームであった・ソースコード以外の設定ファイルはcpコマンドでバックアップとるだけだった)
  • Javaで実行時間を計る方法を、LocalTime.now()以外の見やすい方法を考えておくべきだった
  • アプリケーションの全体を詳細までつかめていない
    • 各エンドポイントが何をするのかわかっていない(そこから呼ばれているメソッドのシグネチャぐらいまでしか目を通していなかった)
  • インスタンスが3つあるのがなぜなのか理解していない
  • DBのスロークエリログと、アクセスログで一番上の事象を改善してもスコアにあまり反映されないことの理由に気付くのが遅い
    • 一番のボトルネックを解消しないと他のアクションの効果が薄いという旨の記述が書籍「達人が教えるWebパフォーマンスチューニング」にあったのに
  • 最後に再起動実験をしなかった(レギュレーションを読んでの、当日やることリストを作るべきだった)
  • MySQLやNGINXの設定のセオリーがわかっていない
    • 設定項目を見ても何についての設定なのか理解できない
  • 触ったことの無い技術要素であるSQLiteに忌避感が出てしまった
    • なにをやってるか理解できなかった
  • Gitを経由せず、サーバーのコードを直接書き換えた方が機動力があったかもしれない(VScodeでできたような…)
  • 自分はインフラ関連が未熟で、ソースコードを見ることしかできないのだから最初の時点で気合いを入れて全部のコードを見て分かりやすいようにリファクタリングするぐらいの強い気持ちを持てばよかった
  • 一緒に参加する友達がいなかったorz

総じて…

あまりにも広い範囲で能力が足りていませんでした。普段の仕事が整備されたものであることや、自分で作るアプリケーションは作りきりで終わりだったり複雑なインフラを必要としていないこと等、知識・経験両方が不足していることを強烈に感じています。 今回参加することでこれらの課題に気付けただけでも大きな収穫になったはず…

ネガティブなことが多いですが、曲がりなりにも計測し改善するというサイクルを予選中にできたことや、業務でほぼ経験のない高パフォーマンスのためのSQLチューニングを少し実践できたことなど、成功体験も積めました。

次回の開催の時までにもっと力をつけて来年も参加したいと思います!!