【最終スコア1901】ド素人がISUCONに出た結果、、、

# お断り

全国の猛者が、ものすごいスコアを叩き出しブログを書いてるなか、同じような境遇の人も多いはずなので、FAILしなかった者の記録として残します。

# 最初にまとめ

- ISUCON出場は、一人でも、過去問を解いてなくても、素振りしてなくても、出るメリットはある
    - エンジニアとして強み弱みを把握できる
- 近年の出題傾向的に、(技術だけでなく)アプリの「仕様」を把握しないと太刀打ちできなそう
    - (単なるスロークエリ改善だけのような)純粋な技術面の改善ではスコアが上がりにくく、アプリのシナリオを把握し、改善をかける必要がある
    - 仕事でやることと何も変わらない、、、?
- 強くなくても、準備不足でも、スコアがOOでも、得られるものは大きかった！


# はじめに

ISUCON14に初出場しました!

出場時の条件は下記です。

- 5年目バックエンドエンジニア
- 実装言語はPHP
- 一人チーム
- 準備期間は約一ヶ月

結果として、最終スコア : `1901点`、順位 : `416/834位`[^1]でした！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290859/2a5c0dea-a76f-38d6-36fb-39489bb7fc9e.png)

# 準備期間にやったこと

長いので読み飛ばし推奨。

## 1ヶ月 ~ 3週間前


ISUCON本の1~3章 & private-isu攻略10ページ を読み、そもそもボトルネックって何?、というところからインプットしました。

https://gihyo.jp/book/2022/978-4-297-12846-3

また `catatsuy/private-isu` のAMIを起動し、ISUCON本の回答を見ながら2万点前後まで点数を上げてみましたが、「ここでかけてる改善を当日シュッとかけられるか、、、?」と不安に、、、

https://github.com/catatsuy/private-isu

## 2週間前

よって、「もう間に合わないから秘伝のタレ(当日のデプロイ&計測用をシュッとできるスクリプト)を仕込むか！」と ~~この時点で若干諦めていますが、~~ 準備の方向性を変えてみました。

例えば、下記を準備しました。

1. 秘伝のタレ(当日の便利スクリプト)
1. 当日用チートシート
1. 当日TODO

またいろいろな猛者が秘伝のタレを公開していますが、かなり作り込まれており、自分の理解の範疇を超えていたので、大人しくオレオレshell scriptを仕込んでいました(作りがアレなのであまり公開したくない)。

また下記の神資料でSSHやGit管理の練習をしました。
(最近の業務ではgit -> ghコマンド、 ssh -> aws ssmだからあんまり慣れてないんですよね、、、)

https://isucon-workshop.trap.show/

## 1週間前 ~ 前日

過去問の素振りをしよう！、と下記の神リポジトリを参考に、ISUCON13の問題を見てみましたが、「いやprivate-isuよりずっと複雑やんけ、、、」と絶望したので、素振りは諦めてslow query log, access logなど計測系の練習をしました。

https://github.com/matsuu/aws-isucon

準備の最後には、ISUCON本を参考に、slow query, nginx logの出し方をもう一度練習しました。

## 当日の記録

### ベンチ計測前

朝8時頃起床し、9:40からのYoutube Liveにつないで待機。

10:00から競技開始した後、ドキュメントを読みます。

https://gist.github.com/wtks/8eadf471daf7cb59942de02273ce7884
https://gist.github.com/wtks/0a3268de13856ed6e18c6560023ec436

長い、、、でもSSEとか通知のポーリング間隔とか、改善には使えそう?のようなメモ書きは残せました。
(しかしその点に関しては何の成果(改善も)得られませんでした)

マニュアルを~~流し~~読みした後、仕込んだ当日TODOに従い、秘伝のタレを動かせるよう~~その場しのぎの~~修正をかけます。


https://github.com/yasuaki640/isu-secret-source/commit/da2abe48c649690f151edd91fcdddae72b364388#diff-fa82dccb6bbae7038ccc0cf4a78a411a47ecb7719791bfb9ae6935cf855412fe

ここまでで11:30でした、、、

### 初期ベンチ実行 (426点)

当日のマニュアルに従って、実装をPHPに切り替えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290859/d3e93487-3999-d4c9-efb7-2cce795c678f.png)

426点、、、Goの実装の半分くらいになりましたね、、、

topコマンドでプロセスごとの負荷を見ると、やはりmysqldが最上位でした。

ここで最初の判断ミスをします。
「じゃあクエリの負荷だけ見てればそこそこ点数取れるのでは??」と **(実際のボトルネックである)アプリのロジックをフルシカトしてしまいました、、、、**

### とりあえずindex追加 (935点)

`ODER BY created_at DESC` ねらいのindexを追加

https://github.com/yasuaki640/isucon14-webapp/commit/c62bf3a669d402c1995462adf0afc1ef35372ac6

### chairsのselect条件にowner_id追加 (1522点)

クソデカクエリのサブクエリで、フルテーブルスキャンしてたみたいなので、`WHERE IN`で絞り込み
(クエリ自体はchat gptに出力させています)

https://github.com/yasuaki640/isucon14-webapp/commit/f75064440df68a7788bc66c38b02574dc642d9ff

### index追加まつり (2008点)

競技終盤でお手上げだったのでとりあえずクエリ追加

https://github.com/yasuaki640/isucon14-webapp/commit/3a355c36c1eb1c32ca77c1a667e3906c08b1e213

https://github.com/yasuaki640/isucon14-webapp/commit/5ec7e5657b8dbc128b3fca6b687a3ac6d9a1868f

### 最終ベンチ回し直し (1901)

そして再起動試験の時間ができなかったため、mysql, nginxなど設定ファイルを見直してベンチし直し

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290859/5f11bf1a-ff96-279f-4550-f991e3e9c75d.png)

そしてslow queryなど**ログを切り忘れのまま**finishしました、、、

## 出場してわかったこと

### 「仕様の把握」が自身の課題

練習では、過去問の素振りができず、近年の出題傾向(シナリオベースのボトルネック改善)を把握していませんでした。

そのため競技中は「とりあえずスロークエリを改善したらいけるやろ〜」と視野を狭めてしまいましたが、本番ではアプリケーションの仕様とロジックがボトルネックだと気づかず、時間を浪費してしまいました。

自身は本業でも同じ傾向が強く、アプリケーションの問題に対して、見えてるコードベース内で考えてしまうため、要件/要求など、より抽象的な観点から全体を俯瞰する習慣が必要です。

### ドキュメントを読んだうえでの改善ができなかった

当日にアプリケーションマニュアルを見たところ、その長大さに圧倒され、早く読み終えようと焦ってしまいました。 (LOOKにとどまった)

改善できそうな点について、メモを取れたことは良かったですが、出題傾向を把握してなかったこともあり、競技中は素通りしてしまいました。

また最終スコアの扱いについても読み飛ばしてしまい、最終計測でロギングを切れませんでした。

### 事前準備は(初回にしては概ね)実施できた

即効性のある施策(自動デプロイ準備、Git SSH練習)は概ね準備でき、1時間ちょっとで自動デプロイ & ログ出力の環境を整えられました。

しかし、まだまだオペレーションに課題があり、ツールやドキュメント等も改善が必要です。 
(特にチームメンバーが入ってきた場合はドキュメントもわかりやすく書く必要がある)

## 次にやること

### 問題を整理するくせをつける

計測結果や(実務なら)機能リクエストだけみて、じゃあ手を動かそう、ではなく、根本の原因はなにか? そもそも何が問題なんだっけ? と一歩立ち止まる習慣をつけたほうが良さそうです。

具体的には

- 適切な問題設定してから、手を動かす段階を踏む
    - 事象に対して、まずは「結局どういうことが言えるんだろう?」と考察する
- 問題に対して、チームメンバーと対話し立ち止まって考える

などの取り組みが効きそうです (答え合わせはまた来年)

### まずはコードやログが出てきた経緯(要件/要求定義/設計)を意識して実務をこなす。

要件/要求から落ちてきた仕様の経緯など、コードの意図を汲み取る習慣がまだまだ弱いです。

そのため

- (実務では)要件、システム化の目的を確認しやすい場所に記載
- (ISUCONでは)アプリケーションマニュアル -> 仮説設定 -> 改善の素振り

などで習慣づけ出来そうです。

### 近年の問題の素振りをする

やります！

### メンバー集め

やります！

# まとめ

スコアに似合わぬ長大ブログが出来上がりましたが、スコアが低くても学びはたくさんあります！

来年は200位くらいに入れたらいいな、、、

以上。

[^1]: https://isucon.net/archives/58837992.html