2019-09-07 (Sat) [長年日記]
_ ISUCON9予選参加
社内Slackで原君が「ISUCON9の登録が8/25までなんですが興味ある人います?」と言っていたので手を上げたらISUCON初参加することになった。当初は原君、橋本君と三人で出る予定だったが、橋本君が出られなくなってしまったので代りに佐田君に参加してもらった。
チーム名: yarunee
リポジトリ: https://github.com/shugo/isucon9
以下、だいたい時系列にメモ。
- 10:10くらいに会社に着いたものの、誰もいないので帰ろうかなと思ったが、会議室にいた(集合場所はちゃんと決めましょう)。
- とりあえずコーヒーを多めに淹れてポットに用意。
- /home/isucon/isucari/webappをGitHubに上げようとしたが、画像ファイルが多いのでrubyの部分だけGitHubに上げた。
- 何か自分だけ会議室の無線LANの速度が出ないので、LANケーブルを探してきて有線LANに変更。
- 佐田君がインデックスを作成。
- 原君がproductionモードへの変更やログの設定。
- 過去のISUCON情報をぐぐって alp というツールで
alp -r --sum --aggregates='/users/[0-9]+\.json,/items/[0-9]+\.json,/transactions/[0-9a-f]+\.png,/upload/[0-9a-f]+\.jpg' -f /var/log/nginx/access.log
とかして/users/transactions.jsonの実行時間合計が長いことを特定。 - かつふじのチキンカツ定食・親子丼をおごった。
- MySQLのスロークエリをログに出すようにしたが、0.5秒以上のクエリは3つほどしか出ず/users/transactions.jsonとは関係なさげ。
- items.created_atのインデックスを追加。
- /users/transactions.jsonのsellerをJOINするようにしたがあまりスコアは上がらず。
- categoriesが40件くらいしかない&get_category_by_idが再帰的にSELECTしていて遅そうだったので、JOINするのではなくメモリにキャッシュするよう修正。
- 冷蔵庫にあったアイス(お中元だったらしい)を振る舞った。
- buyerもJOINするよう修正。
buyey
というRuby版のtypoを運営に報告。ベンチマーク通ってたのでこの部分削っても動くんだろうけど、コンテストの趣旨に反する気がするのでtypo修正。- STDERR.putsでプロセスID、スレッドID、処理開始からの経過秒数をsyslogに出力して、外部API呼び出しがボトルネックと特定。
- 外部API呼び出しの結果をレスポンスに含めているので、非同期化してスループットを上げるのはかなり構成変えないと難しそうで悩む。
- api_client.shipment_statusがdoneを返すケースが多そうなことをログで確認。
- transaction_evidences.statusがdoneの場合はAPI呼び出しを省略してdoneを返せばいいのではないかという仮説を立て、原君にドキュメントで状態遷移を確認してもらった上で実装。ベンチマークも通った。
- 佐田君がMySQLの何かのパラメータをチューニング。
- この時点でまだアプリケーションサーバのスケールアウトに成功しておらず、諦めてDBサーバだけ別インスタンスにするよう方針変更。
- 例外が握りつぶされてdb errorとだけ表示されていたりしたので、例外の内容やバックトレースをログに出すように原君に修正してもらった。
- しかし、17:45くらいになってもまだ上手く行かないので諦めムードの中、原君がnginxの設定ミス(スケールアウトの設定が残っていた)に気付いて修正。
- 一応ロードバランサーも別インスタンスにして(効果はなかった)、pumaのプロセス数を調整(IO待ちが多そうなのでスレッド数も調整すればよかったと後で気付いたが、そもそもちゃんとスレッドセーフになってたのか?)。
- 終了時刻が16:10に変更されてロスタイムがあることに気付いたのでインスタンス再起動を試すも、ベンチマークは間に合わず。
構成変更は原君と佐田君ががんばってくれていたが、ファイルアップロードとかもあったので特定URLはスケールアウト対象から除外するようにしたのに商品数の不一致でベンチマークが最後まで通らなかったのは謎。このあたり自分はあまり把握してないので原君が書いてくれるはず。
結局たいしたことはできなかった気がしたが、ぎりぎり予選通過することができた。 なぜか本戦は上位3チームだけだと勘違いしていたので予選通過できると思っていなかったけど、東京まで行かないといけないらしい。どうしよう。
今思えば、単一リクエストの処理中に外部API呼び出しを複数回やってるのをThreadで雑に並列化するだけでもスコア上がったかもしれないなあ。