ISUCON2018に参加してきました

こんにちは、Webエンジニアの@sat0yuです。 先々週末9/16(日)にISUCON8に参加しました。少し時間があいてしまいましたが、今日はその報告を記します。

ちなみに今年のISUCON初参加を通して、 来年はQuipperから10チームでISUCONに参加することになりました

screen shot 0030-09-25 at 11 31 25

なお、本投稿ではISUCON自体の説明は割愛させていただき、すでにISUCONを知っている方を想定読者としています。

Quipper社員のみで構成されたチームでのISUCON参加は今年が初めてです。 (内輪ネタですが昨年にリクルートマーケティングパートナーズの社内ISUCONへの参加がありました)

他のブログ記事でも多く言われていることですが、ISUCONでは参加する過程において得られる多くの学びにこそ本当の価値があります。 普段とは少し外れた領域で技術的挑戦を行うことや、問題解決に向けたチーム内でのディスカッションを通して、エンジニアとしてのスキルを大幅に向上できると考えています。

言わずもがなですが、Quipper&リクルートマーケティングパートナーズはISUCON出場を業務扱いにしてくれるエンジニアに優しい会社です。

screen shot 0030-09-25 at 11 33 59

チーム「予選落ち」

弊社エンジニアの @ujihisa @chaspyとチーム「予選落ち」を結成しました。今年のISUCON成果は予選落ちでした。

事前に明確な役割分担は決めていませんでしたが、普段の業務内容との親和性から@chaspyがインフラ&ミドルウェアを、@sat0yuがアプリケーションを、@ujihisa が全体指揮をして昨年の経験・知見を最大限に活かして動くことを想定していました。 また、アプリケーションの言語としてはQuipperで普段から使われているrubyを選択しました。

準備

じつは準備らしい準備は全くできていませんでした。

予選一週間前になってはじめてチーム全員が集まり、唯一出場経験のある@ujihisa から一通り競技の流れを説明。 説明に基づいて課題点の洗い出しやToDoのブレスト、残り一週間をどう動くかについて話すなどしました。

あとで振り返りでも述べますが、競技を終えた今では「ISUCON一週間前の準備」としては「競技中にどうやって戦うか」に焦点を当てた模擬戦のような練習こそが必要だったのではないかと考えるに至っています。

予選当日

ISUCONのルールでは、サーバーの再起動後でもアプリケーションが正常動作することが求められています。 我々は余裕をもって再起動テストを行うために、事前に「 17:00以降は大規模な変更を禁止する 」こともチーム内の約束としてしました(競技終了は18:00)

また「推測するな、計測せよ」とはISUCON界隈ではよく言わている格言です。 我々もこの大原則に従って「 ボトルネックが分かるまでは手を出さない 」ことを決めていました。

あとで振り返りますが、最初に決めたこの2つの約束に拘りすぎてしまったことも反省点です。

  • 17:00以降は大規模な変更を禁止する
  • ボトルネックが分かるまでは手を出さない

計測

「推測するな、計測せよ」を実践するために具体的に行ったアクションは以下のとおりです。 とくに(a)環境整備〜(c)データベース理解までは3人で1つの画面を眺めて作業を行うことで情報共有を効率化しました。

  • (a) 環境整備
    • SSH有効化
    • 必要ツールのインストール
    • 設定ファイル&アプリケーションコードのバージョン管理
  • (b) サーバー初期構成理解
    • 1サーバー(以下isucon-aと呼ぶ)がデータベース(MySQL)・バランサ(H2O)・アプリケーションを全装備
    • 提供された3サーバーは互いに非連携
  • (c) データベース理解
    • MySQL WorkBenchのreverse engineeringを実行しER図を自動生成
      • 産業革命だ!」の叫び声とともにここで計測フェーズ最大の盛り上がりをみせる
    • データベースにはリレーションが存在しない
    • 各テーブルの索引有無
  • (d) デプロイ自動化
    • アプリケーションのデプロイ
    • 設定ファイルの配備
    • アプリケーション&ミドルウェアの再起動
    • ログローテート
  • (e) アクセスログ解析
  • (f) サーバー利用状況の把握
    • htopによる断面的解析
    • datadogによる経時的解析

じつは以上の項目を全て完了した時点で15:00に達していました。 当初の約束を守るためには残り2時間で ISU (Iikanjini Speed Up) しなければなりません。

ボトルネックが分かるまでは手を出さない」という原則に囚われつづけてしまい、タイムマネジメントを行うことができませんでした。

計画・実行

入念すぎるほどの計測の結果、すでにいくつかの改善案が3人の頭の中にあったため、残り2時間をいかにして効率的に使うかが論点でした。

10分程度の議論を行い、以下2点の改善に集中すること決定しました。

  • (1) アプリケーションコードのリファクタリング
    • H2O & Pumaのアクセスログ解析結果を比較
    • get_events & get_event メソッドが遅延のボトルネックであると特定
    • コードを一見しただけでもN+1問題の存在を確認できた しかもよく見るとN+1どころじゃないさらに深いループとロック
  • (2) サーバー構成変更
    • htop & datadogで計測
    • ruby実装ではメモリが逼迫され、大量のスワッピングが発生
    • せめてデータベースとアプリケーションを別々のサーバーに分けたい

なおデータベースの索引検討も行いたかったのですが、上記2メソッドにおけるクエリではすでに索引を利用していたため着手項目からは外しました。

残り2時間でのエンバグは致命傷となるため、(1)リファクタリング@ujihisa@sat0yuがペア・プログラミング体制で取り組み、(2)サーバー構成変更は普段からインフラ操作している@chaspyが担当することにしました。

結果としては、 get_events 経由の get_event 呼び出しにおいてN+1問題のうち一つ解決しスコアを5,000程度まで伸ばしました。 一方で、サーバー構成変更に関しては2時間での解決が困難を極め残念ながら解決にいたりませんでした。

当初に定めた約束を守った見返りとしては、最後の1時間には余裕をもって再起動テストを行ったり、無駄な計測コードを取り除く余裕を持つことができました。

振り返り

競技終了後、熱が冷めないうちに反省会をおこないました。 image from ios 1

悪かったこととして挙げられたほとんどの点が、練習不足の一言に尽きると思います。 どれだけ情報を収集したとしても、実際に手を動かしてみない限り文字通り身を持って理解することができませんでした。

とくに、

  • 作業・役割の分担が曖昧だった
  • 改善案が機能しなかった場合の諦める基準がなかった
  • 計測に基づく改善案のアイディアが出せない

などは、実際に過去問を解いていれば回避できた問題かもしれません。

また一方で、良かったこととして挙がってきたことも、実践してみてわかったことが多くありました。

  • 複数人で一緒に行う調査
  • 負荷テストの必要性

最近はQuipperでもペア・プログラミングを見かけることが多くなってきましたが、今回のISUCON出場を通して、「調査」タスクでも複数人で一緒に作業を行うことに非常に効果があることわかりました。

誰かと会話をしながら調査を進めることで、事実と推測の区別が付きやすくなるからです。 同じものを見ているのに何か特別な説明が必要となるのであれば、それが推測である可能性が高いと気がつきます。

また、既にQuipperではCircleCIを用いたテスト自動化を実践していますが、そこに負荷テストは含まれていません。そのため、ユーザ増加によって特定の処理が当初の想定時間をオーバーしてしまう等の問題を事前に回避することができていません。

さいごに

冒頭に述べたとおり、 来年はQuipperから10チームでISUCONに参加することになりました 。 Quipperでは来年度も一緒にISUCONに参加するエンジニアを募集しています! 興味を持たれた方は以下のリンクからお気軽にご応募ください。