ISUCON 4にチーム「ヤキトリ缶(タレ)」で参加したが、いまいちパッとしない感じだった #isucon
先週開催されたISUCON4に、去年に引き続き参加してきました。
チームメンバーは去年と同じ@hisayoshと@qtkmz。チーム名は、去年に引き続きチームミーティングした時に目の前にあった食べ物です。ちなみに去年のチーム名は「勝浦タンタンメン」。
参加日は1日目、仕様言語は去年に引き続いてPython。Goが有利みたいな高度な情報戦も流れていたのですが、去年、Pythonで勝てなかった悔しさから今年もPythonで再挑戦と決めていので、特に言語選択では迷いませんでした。
結果
結果から言うと、タイトルの通りいまいちパッとしない感じで、予選時に提出したスコアは30000弱。予選1日目からベンチマークに見直しがかかったので、更新後のBenchmark v2で、後日確認したスコアはだいたい35000。最終結果の発表は、10/6(月)なのでまだわかりませんが、予選通過ラインには届かなさそうな気配。
今回やったこと
今回やれたこと/やろうとしてやりきれなかったことをざっくり。
- やれたこと
/etc/sysctl.conf net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 30 net.ipv4.ip_local_port_range = 10000 65535
- やりきれなかったこと
前回のISUCON3の予選では、結果として予選の環境とベンチマークに特化したスコア稼ぎで予選を突破してしまった*1ので、今回は普通のチューニングで着実にスコアを上げていく方向で進めたのですが、いろいろ手間取っているうちにタイムアップ。
飛び道具には手を付けず、とはいえ、超絶アプリ改修もなしの至って普通のチューニングです。
自分たちのチームではこの程度のチューニングができれば予選は通過できると踏んでいたのですが、フタを開けてみると今年は去年以上にレベルが上がっていて、4万以上のハイスコアを出すチームが多数。その勝負の舞台に乗りきれなかった感じです。この辺りの読みと判断も含めてISUCONの勝負なんですよね。。。
当日までの流れ
対策ミーティング
僕たちのチームメンバーは、会社もバラバラで一緒に開発した経験もないため、去年のISUCON本戦ではお互いのやっていることがバッティングしたり、開発方針を共有したりするのに手間取ったので、一旦メンバーで集まって、去年のISUCON予選の問題を題材にして、チーム開発の方法を確認。実質的にはGithubハンズオンで、Mergeリクエストベースで開発することを決めて手順確認。
参加者ブログを見ると、1台のサーバ上のファイルを書き換えたという侠気あふれる報告もありますが、それができるのはいつも一緒に作業してて、阿吽の呼吸があるからだと思うんですよねー
なので、一手間かかりますが、Mergeリクエストを送って、各人が編集内容を確認できるようにしました。
去年のISUCONブログを見ても、役割分担を完全に決めてしまって、それぞれの作業は見ないで進めたって話がほとんどなんですが、即席チームだとなかなかそうも行かず。
本当はもっと対策ミーティングをやったり、ミドルウェア系の秘伝のタレを用意したりしたかったのですが、結局なかなか集まる時間を取ることができず、ISUCONがあった週は自分が毎日終電を逃すスパイラルに陥っていたので、最低限の開発手順と視点の共有ぐらいの準備で本番に臨みました。
当日の流れ
当日の流れを箇条書きで。
- まずはAMIを起動して、アプリ確認。銀行アプリかと見せかけたログインするだけのアプリ。
- ベンチマークを掛けてみる。MySQLの負荷が高い。
- 開発環境として、メンバーごとにインスタンスを作成。
リポジトリの作り方をミスって作り直したりしてて30分ぐらいロス。立ち上がりに時間がかかる。
午後一でアプリを読んだ結果を共有
- 最終ログイン時間とログイン失敗数は、usersテーブルに書いておけばlogin_logを舐める必要はない
- banned_ipはip管理用のテーブルを追加すればよさそう。(これは最後まで実装間に合わず)
- 最終的には使わない予定だけど、login_logを舐めるのがヒドいので、とりあえずINDEX貼る
CREATE INDEX id_idx_1 ON login_log (ip, id); CREATE INDEX id_idx_2 ON login_log (user_id, id);
-> これだけで3000 -> 10000〜までスコアアップ
- login_logも初期データがあって、最終ログイン時刻とログイン失敗回数はそのデータを反映する必要がありそう。
- @hisayoshに、awkワンライナーで最終ログイン時刻一覧を作ってもらって、最終ログイン時刻だけ反映するSQLを作成
- usersテーブルに最終ログイン時刻とIPを追加して、ログイン時にアップデートするよう変更。
- 最終ログイン時刻と最終ログインIPの仕様を誤解して、手間取る。
- ここまでの改修で20000を超えるようになったが、ポート枯渇などのエラーが出るので、カーネルパラメータを変更し、Nginxとgunicorn間の通信をUnixドメインソケットに変更。
- このタイミングでMySQLを5.6に変更。skip-innodb-doublewrite、innodb_flush_method = O_DIRECT_NO_FSYNC までなら通常の永続化は保たれてセーフだと踏んで設定。これでちょっとスコアアップ。
- ただ、最終提出AMIへの反映が漏れていたことが、あとで発覚。
- 続いて、ログイン失敗回数をusersテーブルに書き込むようアプリを改修。
- @hisayoshに、awkワンライナーでユーザ・IP別のログイン失敗回数一覧を作ってもらう。
- ただ時間が迫ってきているのに焦って、ログイン失敗書き込みが漏れてFail。泥罠的な修正を加えたため、バグを埋め込んでしまい手間取る。
- ベンチマークはFailなしで走るようになったが、初期データの反映ができていないため、レポートで落ちる。。。
- 結局、安定した時点までのアプリでベンチマークが通ることを確認して時間終了。
以上。
こうしてまとめて見てみると、大したことができてなくてつらい(´;ω;`)
大したことないアプリの改修で、舞台に飲まれてバグを埋め込んで時間を使いすぎました。。。
去年の本戦でも感じましたが、こういった時にすぐに解決策が出てこなかったり、コードを修正するのに手間取ったりするのは、普段からの修行不足。
もう予選も終わり、予選用のリポジトリも公開設定に変更したので、恥ずかしながら、使ったリポジトリのURLを貼っておきます。華々しい結果ではありませんが、ISUCONアンチパターンとして見ていただければ。
予選は双六工場こと、僕の自宅から参加したのですが、うちの周りから上野に掛けてIngressのポータルが多いので、予選後は反省Ingress会をやり、上野の「もつ焼き 大統領」でもつとか馬刺しとか食べて解散。
まとめ
振り返って見ると、いろいろ反省点はありますが、判断ミスややりきれなかったところも含めて、今の自分の実力とも思うので、 予選自体にはそんなに悔いはないです。あとはなにかの奇跡が起こって、運良く本戦に引っかかることを祈るのみ。
ISUCONは、すべての参加者が同じ土俵で戦ってベンチマークスコアのみで勝敗が決まる単純さが面白いですね。非常にわかりやすい。なんとなく、幽遊白書の魔界トーナメントを思い出します。やっぱりこういうお祭りがあると、盛り上がるし、エンジニアの実力がこうやって可視化されるのは、間接的にはIT業界全体にとってもいい影響を与えているのではないかと思います。個人的にも、こういう機会があると普段の仕事の時にも気合が入ります。
最後になりますが、運営のみなさま、出題を引き受けてくれたクックパッドのみなさまに感謝を。貴重な機会をいただき、ありがとうございました。毎年規模が拡大し、参加者にもノウハウが溜まってくる中でISUCONを運営するのは、非常に大変だと思いますが、それが続けられているのも、歴代の運営スタップが真剣に取り組んでくれているからだと思います。予選運営お疲れさまでした。
予選通過は厳しい感じではありますが、いずれにせよ本戦が楽しみです。10/6の最終結果発表を楽しみにしつつ、今日はここまでで。
*1:前回も意図したものじゃなくて、チューニングとして意味がありそうなものを順番に試していったら、うまくいくポイントを見つけてしまったというのが実情なんですが