読者です 読者をやめる 読者になる 読者になる

たごもりすメモ

コードとかその他の話とか。

#isucon2 をやったあとの反省など

isucon

#isucon2をやりましたの話 - tagomorisのメモ置き場

これの続き。主に反省というか振り返りというかについて書きますよ。(誰かが次回っぽい何かをもしかしてやるかもしれないときのために!)

参加層について

今年はいろんな言語が使われたので大変よかったですね!

実際、告知をすればいいというものではなくて、各コミュニティの適切な層に届けるというのはなかなか難しい。告知から参加申し込み受付まではそう期間を空けられないし、参加者総数はそうそう増やせないし*1

それでも参加層が広がるのは良いことだと思う。イベントとして好評なまま回数を重ねることが大事なんじゃないかな。誰がやるにしろ。

問題設定について

今回は(最終的に)トランザクションが問題になるものにしよう、そのために並列度はガツンと上げよう、というのは最初に決めていた。

が、実際には実装のめんどくささを意識してなかった。今にして思うと、較べれば去年の isucon1 のチェッカは超簡単でしたことよ。作業量の見積りが難しいなーというか、このへんはもう諦めて都度乗り切るしか無いかなという気もする。事前の推測がだいぶ難しい*2

更新系の他方、参照クエリもそれなりの重要度は持っていてほしいというか、本当は最初はキャンペーンサイト的なページをさらにもうひとつ作ってそこに対してアホみたいな*3並列度の参照をかけ、まずそこが最初の壁になるようにしようかな、みたいなことも考えた。考えたけど、初期状態でベンチがFAILEDにならないようにできる自信がなかったのでやめました。
「キャンペーンサイト・チケット販売サイトが落ちるからなんとかしろ!」という問題設定であればそういうのもアリだったかも。初期状態でベンチがFAILしないって前提条件は問題を作る上でなかなか高い障壁なので、そこを諦めるのを選択肢に入れられるかどうかが重要なのかな。

チケットの席順ランダムはチェックするつもりでコードがバグってた。この行の最後の&&が、本当は || でないといかんかった。これは素直に反省……だけど、優勝したfujiwara組の解法はランダム制約あっても使えるので、最終的な結果にはあんまり関係なかった。ひと安心。

どういう制約をどこに追加すればどれだけ遅くなる/改善が難しくなるかというのは普段と完全に逆方向の思考が要求されるので、頭の体操というか、普段の思考過程を見直すにもだいぶ良いトレーニングになるかも、という気はする。準備期間中、最初は機能追加に戸惑っていたsugyanはじめ同僚のみなさんが、本番が近付くにつれてどんどん極悪な機能を提案してくるのは見ていてじつに楽しかった。
もちろんいちばん極悪なのはkazeburoさんです。こわい。

ベンチマークツールの作りについて

作業時間内は1分走行、採点時は3分走行というやつ、まあ毎回3分はやってられないと思うのでベターではあったと思うんだけど、内部的には簡単にどちらも指定できるようになってたので、両方のボタンと出しておけばよかった。
他に、高い並列度での負荷をかけず、初期状態チェッカおよび購入チェッカを短時間だけ走らせるモードもあってもよかったかも。

このあたり、ベンチマークツール側の内部構造としては割とがんばって作ってあったのに、それを作業者の便利さにフィードバックするところまで頭が回らなかった。いろいろなパラメータでベンチやチェックを走らせられるようになっているなら、それを提供すべきだったなあ。

あとダッシュボード(チームの状況一覧が出ている画面)の作り、というか情報の表示もいまいちだった。
今回は制限モードというのを作っていて、要するに採点用のモードで有効にすると通常ユーザを画面から締め出す*4んだけど、そいつが有効になっている場合は常に画面にそう出ているようにすべきだった。そうしておけば採点時のベンチ走行ミスもなかったのに。一般のツールだと思い付く(かもしれない)ことでも、ばたばた実装すると割と忘れてしまう。反省。

エラーの表示についても少し問題があるにはある。ドキュメント化とか一切やらずに実装していると、node.jsのコールバックで渡ってくる err という変数の内容が致命的エラー/システムエラーなのか、それともチェック内容のエラーなのか、みたいなのがどんどん分からなくなってきたりする。もしくは、オブジェクトなのかオブジェクトのリストなのか、文字列なのか、文字列のリストなのか、とか。
更にあんまり考えずに通常の結果データ(コールバックの第2引数)に入れるベンチマークのチェッカが出力した失敗についても error アトリビュートに入れちゃったりしたせいで余計カオスに。やばい。書いてて何をどれだけシリアライズしたら目的の文字列が出てくるの、みたいな。

こんなこと書いてると素人かと怒られそうですが、時間が無い中で書けるところからばたばた書く、みたいにやってるとやっぱり良くないですね。

分散ベンチマーク処理クラスタについて

今回のベンチマークツールは、ベンチマーク走行という、数十秒〜数分程度の短いタスクをがんがん分散並列実行するためのクラスタを作ったといっても過言ではありません。期間に対しては割とよくがんばって作った。
実はエージェント側は立ち上げれば立ち上げるだけ簡単にクラスタに追加できる構造になってて、最初に上げてあったノード数で足りなければ余ってるマシンも追加しようかと思ってたくらい。やらなくて済んだけど。

去年はベンチ走行対象とベンチ実行側のノードを固定のマッピングで設定に書いてあって、負荷が高くなったりしても調整が非常に困難という問題があったりした。また頻繁にベンチを走らせる、しかも高得点のチームが隣りあったりするとお互いに負荷や帯域を食い合うという問題もあった。
今年はベンチ起動時に毎回空いているノードから順にひっぱってきてベンチ処理をディスパッチする、しかもベンチ処理タスクを種類毎に分けてそれぞれ個別にディスパッチするという無駄にスケーラブルな構成になってたので、じつに安心だった。

まあ、実際には事前に設定したスロット(ほぼCPU数とイコール)を割り当てるだけの簡易的な負荷分散だけど。やるんなら個別のタスクがCPUネックなのか帯域ネックなのかを事前に設定しておいて、そのへんを更に動的に賢く割り当てる、とかできるかも。でも少し面倒くさいなあ。

このあたりのコードの詳細はあるところに少し詳しく書く予定がある、ので、機会があればそちらをどうぞ。

自分が挑戦するとしたら

って書こうかと思ったけど、自分、よく考えたらISUCONは1も2も、いちども対象アプリを高速化させようと思って触ったことがなかった! おれ、シロウトだった! 書けない!

……というのは冗談としても、まあ後付けなら何でも言えるよねっていうのを言うのは虚しくなったのでやめた。遅くするためにコードいじるのはいくらでもやったんだけどなあw
将来的に自分が参加できるISUCONがやってくる日を夢に見て待っていようとおもいます!

*1:仮想サーバ1台を新規にデプロイするのはデータコピーもあるのでけっこう時間がかかる。それを100台分となると……。そして前日に問題に修正が入ったりするし。

*2:その上そこの見積り精度を上げてもなんにも他の役に立たないw

*3:更新系より1桁くらい大きい

*4:そしてベンチの実行設定を採点フェイズ用のものに入れ替える