どうみても予選敗退です本当にありがとうございました。
ISUCON本戦出場で、人権と職を獲得する目論見はかないませんでした。
結果として最高時スコアは14〜15万あたり、これでは出場の芽がみえないと色々いじってスコアが下がり最終は11〜13万くらいでした。
グラフをみていても夕方頃まではなんとか下をウロウロしておりましたが、相変わらずの伸び悩みです、最後の1時間、思わぬロスタイム*1で気分が代わり、勢い良く大鉈をふるったらスコアがのびたので、夕方に躊躇したのが悪かったと思いますね。
今回3年ぶりにコード書く*2役割だったので、PHPをチョイスし、「ついにフレームワークが最新Slimになった!!!!!」と喜びながらの開発となりました。PHPさいこう!!!!!さすがKlabさん!!!!
感想
今回はすごく素直な課題で、みたことがあるような問題を見たことがあるような感じで解決していきました。
ベンチマーカーもキューがガンガン来てくれるし、エラーメッセージも親切、すぐにFailがわかる!これは最高!本当によかったです。
構成
common.phpという普遍的なチーム名にしたので、ミドルウェアは吊るしのnginx+phpのままです(?)redisとかそういうPHPerが普段使わないであろう(?)ものは使わない事にしました。
HHVM差し替え&組み込みhttpdの投入はすこし悩みましたが、hhvmがPHPからはなれつつある今、矜持は本家!ということで変な差し替えも無し。7.2RC4にするかは迷ったけど(自分はもう普段から使っているし、実際多少速くなるので)、人手が足りないのでパス。
ただ、3台構成を生かすところまでいけなかった、結局2台でゴールです。結果Web+DB構成でウェブのCPU100%、DBのCPUがピーク70%くらいで時間切れになったのが心残りです。*3。
変なところをいじっても性能があがらないのがよい
今回もヘンテコな(本番ではつかわないような)パラメーターブッコミチューニングはあんまり効果がなくて、粛々とリクエストやクエリを減らすとスコアが伸びる、というのがよかったですね、実に競技性がある。
コードをつらつらとよんでいてsleepによるトリックにはウケた、チャットで昔みたことあるテク(?)だ。他の言語ではこのsleepでもいいんでしょうね…。(これを伸ばすなど工夫するとスコアが伸びる…らしいけれど、Preforkのphpでは普通にきびしいので無理。現実で必要ならevent駆動に書き換えるか、クライアントのJs側でwaitをいれなければいけない)
効果があった施策
- インデックスを張る
- sleep()をそっとはずす(js触ってもスコアに関係ないのでDoS状態になるのは放置)
- initなどで画像を書き出す。memory limit調整やtimeoutしないように調整(以下へつづく)
- 画像配信はnginxにやらせてphp経由を減らす、ExpireとCache-Control付与(道半ば)
- N+1をJOINに
- fetchが重いのでクエリを調整し、一部的にキャッシュ(しかしこれではたりなかったので次へ)
- indexが効いてるカラムだけでカウントしても、クエリを一つにまとめて全chのメッセージ件数COUNT(GROUP BY)でも重い。ので、ch毎のメッセージ数をキャッシュするテーブルを作成(次の行へ)
- アクセスパターンをみたら既読無し(=そのユーザー固有ではなくてよい既読数)のchが多いので無駄なループが多い、既読があるchだけcountし、全ch毎の件数テーブルとマージすることにした。
- メモリもCPUを使い切れていないのでコア数無視してワーカー数盛り
まあ、大体DB直してたよね。
効果あったかわからん施策
期待もしてはいなかった。
(最終的に)効果がなかった施策
こういうの、すっぱりと諦めてコードかいてたほうがスコア上がる気はしている(でもどうしてもやってしまう、やりたいからw)
間に合わなかった施策
- 良いワーカー数の選定
- 3台構成(雑に3台にしたらスコアがおちたのはヘッダーだとわかってはいたが…)
残念です。
使ったツール
- Jet profiler(クエリの頻度などの確認に)
- ログ解析はツール使わず、log formatをuriとStatus codeと処理秒数だけの出力にして、あとはcat grep lessと心眼で
- microtime()とerror_log()による温かみプロファイル()
- Chrome(のリクエストをcurlにするやつ)+curl+jq
- コード修正はサーバー上でvim
- CPU利用率はhtopとvmstat
こうやって書くとホント素手以外のなにものでもない気がしてきた。 Jet Profilerは「大量に発行されている(つまり重要な)クエリがなにか」を見やすいのが良いですね、有料だけど。あと、qpsが見れるのでリアルタイム負荷メーターとしてもお役立ち。
しなかったこと
- 秘伝のタレの準備(最後にためしに昔のタレいれたけど、あまり変わらず)
- デプロイツール類の整備(コード書くのが一人なら、なんだかんだ素手のほうが速い。PHPStormにターミナル経由でコピペして整形したくらい)
- ログ解析ツール類の整備(個人的には、過去そんなにやくだたなかった)
- xhprofなど(ISUCONの規模なら、読めばわかるしmicrotimeとerror_log関数で十分)
- phpやnginxの最新版への挿し替え(7.1だったので十分)
- E_NOTICE警察(まあISUCONだしね、しかたないよねw)
- 素振り(本当はやりたかったけど、諸般の事情です)
これらは参考にすべきだとは言わない、何回か参加した個人的な感想です。 良いツールを揃えるのは楽しいし、それはいいと思うんだけど、毎日毎日触っているツールでないといきなりハマると思う。
ハマったところ
- 最初mysqlへrootアカウントでTCP接続できなかったので「grant…grant…」とググる
- netstat -s|grep recovered
- phpのログがどこに出ているかちゃんと確認せずにすすめて、エラーに気づかず手戻り
- explain叩いたらmysqlから反応がなくなってマジで焦ったが、家のインターネットがおちていた。
- 「(タイマーが振動し)ああおわる!全部閉じる!閉じた!おわった!!!!…あれ?みんな盛り上がってないな…?」からの1時間ロスタイムスタート
- 「あとでやろう、とりあえずここはダミーで」→「うごいてないやんけ!!!(自業自得)」
- なんか調子が悪い→systemctl restart isubata.php →直る
まあ兎も角
とてもおもしろかったですね!他にPHPで参加した人と話したい!!
最近はphp以外のコードを見ているので、久々にPHPのコードでチューニングできましたし、根回しの必要無しにガンガンチューニングできるのはたのしいですね!!!
もしまた開催されるようでしたらば是非参加したいと思います!
運営チームのみなさま、本当にありがとうございました!!
わたしの方面の関係者へのご連絡
今回は事前の素振りはせず、当日の12時から23時まで(このエントリ含む)の参加でしたので、ちゃんとやっています、大丈夫です。やっています、本当です。