ISUCON6予選をC++で参加して予選通過した話

2016年9月公開

ISUCON6予選をC++で参加して予選通過した話

チーム名「Anago」で @iwiwi, @zuisou, @imos の 3 人で ISUCON6 予選に参加し,幸運にも 1 日目 3 位で通過することができました.@iwiwi が「ISUCON に C++ で参加したい!」と言っており,それを全力バックアップをしようと思ったのがきっかけの参加でした.

前日までにやったこと

C++ で全てを書けば最速になるのは自明なのですが,C++ は参考実装として与えられていないだけではなく,HTTP サーバを書くことを想定していない言語のため準備には苦労しました. C++ で HTTP サーバを書く方法は,既存の Web サーバ (e.g., nginx, Apache, H2O) のプラグインを書いて実装するか,FastCGI として実装するか,フルスクラッチで書くかの選択肢が考えられますが,プロセス間通信を避けて爆速にしたかったので,事前に nineserver という HTTP サーバを書きオープンソース化しておきました.nineserver の思想は sql.cc が端的に示していますが,
  • 同じファイルをいじる必要がないようにし,共同で開発してもコンフリクトしないようにし,
  • SQL や Web 特有の関数(URLエンコード,HTMLエスケープ)等を用意し,
  • 全て再実装することは諦め少しずつ実装ができるようにしました.
フルスクラッチで HTTP サーバを書くのは色々と学ぶことがあり非常に面白かったです.スレッドプール方式は速度が十分出なかったため,全スレッドが accept で待つ仕様に変えたところコネクションが切られなかった時にスレッド枯渇する問題が発覚し,最終的に半分のスレッドが accept で待ち,残りのスレッドが poll で待つような仕様になっています.想定してない変更を何度も加えたためにコードが汚くなったのでいつか書き直したいところです.

当日やったこと

まず,C++がビルドできる環境の構築しました.apt-get install で Java 9 がインストールできないトラップにはまりつつ Java 8 をかわりにインストールしました.初期実装のポートを変更し,nginx → C++ → nginx → PHP のような構成にして,プロファイリングを行いました.最初のベンチマークのスコアは稀に 0 点がでるなどあまり安定したものではなかったですが,2000 点ぐらいだったように思います.
コミットログから時系列を掘り出すと以下のような感じに.
  • 10時半頃 … 最初のプロファイリングが完了し,各自コードを読み始める.
  • 11時半頃 … 参考実装をレポジトリで少しずつ改変できるようにする (imos)
  • 12時頃 … phpMyAdminのインストール (imos)
  • 13時07分 … SQLのチューニング (zuisou)
  • 13時54分 … セッションをストレージではなくCookieに保存 (imos)
  • 14時22分 … セッションにuser_nameも保存 (imos)
  • 14時28分 … /stars を C++ で完全実装 (iwiwi)
  • 16時55分 … / と /keywords/* キャッシュの実装完了 (zuisou)
  • 17時21分 … HTMLify をトライ木を使って C++ で実装完了 (iwiwi)
  • 17時37分 … PHP の HTMLify を完全排除 (iwiwi)
  • 17時46分 … /keywords/* を C++ で完全実装 (imos)
永続性は SQL への INSERT は残すことによって解決し,初回起動時と /initialize が呼ばれたときに SQL から読み出す仕様にして解決ました.自動起動の仕組みは systemd がうまく使えなかったために,cron で毎分起動する仕様にしました(2 度目以降はポートが開けなくて自動的に終了するので多重起動しないという仕組みです).
図: 最終提出時のスコア状況

感想

最終提出に手間取り,本来であれば一番フロントの nginx を排除したり,デバッグモードを解除したりするつもりでしたが時間が取れませんでした.参考実装をレポジトリで開発できるような環境を整えるのに最初の 2 時間程度を取られるので,その点も改善したいところです./ の C++ での完全実装はあと 30 分程度余裕があればできた気がするので,若干その点は心残りですが予選を 3 位で通過できたので満足できています.