Coder Social home page Coder Social logo

isucon's Introduction

ISUCON

公式の過去問レポジトリ isucon

過去問の実行環境を整えたいならここのvagrantとansibleを使うと便利 matsuu/vagrant-isucon

問題を解く

各種言語で実装されたウェブアプリケーションがMySQLをデータベースとしてシングルインスタンスで動いているので、そこに大量のリクエストが来たときに上手にさばけるように改造する。 ただし、レスポンスの内容は基本的に一字一句変更できない(例えばJavascriptファイルをminimizeして、たとえ表示内容が変わらなくてもNG)(クッキーの中身とかはOK)。

まずやること

大会が始まったらまずやること

  • ルールをよく読む
    • 解法を探るためのヒントが落ちていることがある
    • こういう場合はこういうレスポンスを返しても良い、というルールをうまく活用することでスコアが伸びることもある
    • スコアの方式は毎年微妙に変わったりするので要注意
    • 再起動試験などの手順はよく確認しないと最悪の場合失格になる
  • 問題プログラムを共有する
    • サーバー上に置いてあるプログラムファイルをローカルに持ってきて、Githubなどでチームメイトと共有する
    • シングルファイルで構成されているので、エンドポイント毎にモジュール分割するとコンフリクトが少なくいいかも
    • 使わない言語の実装は適宜取り除くといいかもしれないが、移植時のバグの可能性を考えてGo言語のものはリファレンスとして残しておいてもいいかも
  • サーバーの構成を調べる
    • CPUの数、メモリ、ディスク容量、使われているDBなど
    • 年によってはサーバーごとにメモリやCPU数が違ったりするので注意
  • ボトルネックを探る
    • アクセスログや実装を見てあげることでどこがボトルネックかを分析することでどこに高速化できる余地があるかを探すのがまず第一
    • 言語のプロファイラ、アクセスログをalpで解析する、pt-query-digestでSQLのスロークエリを探す、など

解法の方針

高速化するにはだいたい以下のようなことをしていくと良い。

  • マルチインスタンス化
    • そのままサーバーを複数立てるだけでは当然駄目なので工夫が必要。
    • ちゃんとロードバランスする以外にもエンドポイント毎に役割を分ける、静的ファイル配信専用サーバーをつくる、など
    • 場合によっては変にマルチインスタンス化するよりもシングルインスタンスの性能を詰めてしまったほうが速い、ということもある
  • チューニング
    • nginxやmysqldの設定をいじることでパフォーマンスが向上する
    • どこが遅い原因かを考えながら設定する
  • データベースとの通信の最適化
    • N+1問題の解決、必要なカラムのみをとってくるようにする、など
    • 不変なデータが置かれている場合もあるので、そういう場合はメモリに載せてしまう、プログラムに埋め込んでしまうなどの工夫をする
    • テーブルに新たなGenerated columnを追加することでクエリが最適化できることも
    • データベース以外にも外部APIの通信がある年もある。こちらも呼び出し回数の最小化、並列化などで最適化できる場合がある
    • Redisなどの異なるデータベースを使えば高速化できる可能性がさらに広がる、が実装は複雑になる
  • ユーザー認証
    • bcryptによるhash化は遅いのでストレッチング回数を減らすこと、そもそもアルゴリズムを変えてしまうことにより高速化が可能
    • この部分はISUCON9の予選で判定が紛糾したこともあるので、変更不可となるかもしれない
  • 初期実装にバグがあることもある
    • 特にGo言語以外だとバグっている可能性は高くなる。過信は禁物。
    • 部分的に改良しある程度高速化が進むと顕在化する

開発の仕方

この辺は個人の好みの問題もあるのでチーム内で要相談

短時間の開発で、変更が容易に反映されることを目指した方針

  • ウェブアプリのデプロイはrsync等でコンパイル済みのものをアップロードする
    • サーバーは貧弱でコンパイル時間が長くなることも
    • Windows・Macユーザーの場合、ちゃんとサーバー上で実行できるLinux用バイナリが吐けるか要確認
    • Gitレポジトリを経由する・CIを使うとかは時間が限られたコンテストの障害になるので避ける
    • サーバー毎に変えたい設定は環境変数経由でコントロールする
      • systemdのEnvironmentFileが例年だと設定されているので、それを使うと便利
  • /etc以下の設定ファイルはetckeeperに任せ、リモートのGitレポジトリは経由させない
    • リモート経由だとパーミッション設定とかで面倒なことになる
    • サーバーごとに微妙に設定を変えたい場合も困る
  • サーバー上のDBの状態を確認したい時はSSHトンネリングを使うと便利
    • ssh -fNL <local port>:localhost:<DB port> <remote-addr>
  • ベンチマークを走らせる前の処理・後の処理はシェルスクリプト化するなどして自動化するとよい

準備しておきたいこと

例年の傾向からおさえておきたい知識

mysql

大体、mysqlのN+1問題を潰すのが大きな仕事だったりするので、mysqlの文法はきちんと勉強しておくといい

チューニングはまずはスロークエリのしきい値を0にしてしまってからmysqldumpslowpt-query-digestで解析してあげると、どのクエリが頻繁に呼ばれているか、どこを集中的にチューニングするべきかがわかる。 参考:スローログの集計に便利な「pt-query-digest」を使ってみよう

Rows sentがRow examineに対して大きすぎる場合、indexを貼り直すことを検討する。複合インデックスを用意しておいた場合でもFORCE INDEX句を付けないとちゃんときかないこともあるのでEXPLAIN句でどのインデックスが実際に使われているか確認する。 参考:オトコのソートテクニック2008

さらなるチューニング(クエリキャッシュのサイズなど)はMySQLTunerを使って何が悪いかを突き止めるといいかも? 参考:MySQLデータベースのパフォーマンスチューニング

ansible

このレポジトリの下に過去に自分が使ったansibleが置かれている。コンテスト開始直後にとりあえず走らせるというのができると気が楽なのでおすすめ。複数サーバーに対しても走らせられるし。 よく使うコマンドのインストールや簡易版のvimrc以外にやっていることとしては

  • /etc以下のファイルをgitで管理するためのetckeeperの導入
  • CPU使用率やネットワークの使用率などをリアルタイムに監視できるウェブインターフェースを提供するnetdataの導入-

nginxのアクセスログからボトルネックを探る

alpというのがISUCONではよく使われる。

アクセスログを特定のフォーマットにすればnginx以外でも利用可能(ISUCON8で使われたH2Oとか)

nginxのチューニングやテクニック

便利そうだが自分は使ったことのないもの

Varnish

公式ドキュメント

キャッシュ機能を持つリバースプロキシとして使える。nginxとウェブアプリの間に挟むことでレスポンスを手軽にキャッシュできるらしい。 変更がないデータ以外にも、更新にタイムラグが許されているエンドポイントに使うとかの技がある。

Redis

公式ドキュメント

Key-Value型のインメモリデータベース。データベースの一部カラムをRedisで管理することで高速化できたりするはずだが、大抵変更量が多くて下手に手を出してもうまくいかないことが多いように思える(個人の感想)。 使うつもりなら事前練習をしっかり積んだほうがいい。

Proxy SQL

公式ドキュメント

MySQL 8以降だとクエリキャッシュが効かない。かわりにProxySQLをかますなどでキャッシュできる。 が、本来の用途は冗長化とかにあるっぽいので、果たして有効な手段かわからない。

過去の講評とか

isucon's People

Contributors

cympfh avatar garasubo avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.