C# (ASP.NET Core) でもisuconやってみたい
えーと今日はもう12/28ですが、この記事は .NET Core Advent Calendar 2016の10日目の記事 兼 ASP.NET Advent Calendar 2016 の17日目の記事だということにさせてください。。。
isuconというのは「いい感じにスピードアップコンテスト」の略です。公式ブログによれば
ISUCONとは
お題となるWebサービスを決められたレギュレーションの中で限界まで高速化を図るチューニングバトル、それがISUCONです。過去の実績も所属している会社も全く関係ない、結果が全てのガチンコバトルです。
というものです。雑に捕捉すると、既定の時間内に、与えられたサーバー、ミドルウェア、アプリケーションをチューニングして、時には(レギュレーションの範囲内で)全とっかえして、ベンチマークのスコアを上げるという大会です。
アプリケーションは運営側が参考実装したものが提示されます。直近の大会(isucon6)のオンライン予選では、Perl/Ruby/Python/PHP/Node.js/Go/Scalaでの実装が提示されていましたが、実際に参加したチームを見るとC++やJavaで再実装したチームがあったりするわけです。
まあそんな感じで楽しそうなので、.NET Coreで参加できないかなーなんて思ったりするわけです。
過去問はgithubで公開されている上、matsuuさんがいろんな環境用にportしています。とりあえず今回はisucon4の予選問題でちょっと試してみました……が、なかなか時間がかかりました。
matsuuさんが作成されたAnsible Playbookをベースにしたのですが、こちらはCentOS6ベース。ところが.NET CoreはCentOS7.1以降をサポートとあります。「と言ってもCentOS6でビルドすれば動くんじゃ?」と思って試してみたら、まあそんな簡単なものではなく。結局あきらめてCentOS7ベースにしました*1。その際に、ちょっとうまく動かなかったところがあったので、フォークして雑に上書きしました。
インストールには CentOS 7 Minimal ISOを使いました。
rootでログインして、以下、雑に上書きした https://github.com/matarillo/ansible-isucon を動かします。
$ yum install -y epel-release git $ yum install -y ansible $ git clone https://github.com/matarillo/ansible-isucon.git $ cd ansible-isucon/isucon4-qualifier $ ansible-playbook -i local playbook.yml
もし、途中の 02_supervisord.yml あたりで (追記: ansible側を修正して対応しました。)Could not find the requested service "'supervisord'":
といったエラーが出てたら、systemctl daemon-reload
を実行した上で、ansible-playbookを再実行してみてください。
さて、このAnsible Playbookを動かすと、isucon4の公式リポジトリをフォークして雑にASP.NET MVC Coreアプリケーションを追加した https://github.com/matarillo/isucon4 が組み込まれます……が、まだ中途半端な出来です。
.NET Core SDK 1.0 Preview 4 build 004233を手で入れてください(追記: ansible側を修正して対応しました。)- .NET Coreアプリケーションを手で起動してください
前者はもう単純に手抜きです。時間があったら対応したいです。(追記: ansible側を修正して対応しました。)後者は、公式の仕組み (supervisord) でサービス化しようとしたのですが、残念ながら500エラーが解消できませんでした。こちらも対応したいですが、正式版リリースとどっちが早いかな…
ともあれ、.NET Coreアプリケーションを動かすには、ISUCON4 予選当日マニュアル を参考に、
supervisord
を止める/etc/supervisord.conf
を修正して、すべてのアプリケーション をautostart=false
にするsupervisord
を再開する
とした後*2、
$ cd webapp/csharp $ dotnet restore $ dotnet run
でアプリケーションを動かします。
動いたかどうかはブラウザからポート80*3にアクセスするのが一番いいのですが、CentOS 7の初期状態ではファイヤーウォールがポート80をブロックしているはずなので、『CentOS7のfirewalldをまじめに使うはじめの一歩(systemdも少し)』 などを参考にポートを開けましょう。
さて、この状態で動いているアプリケーションですが、公式の参考実装を移植した体になっているので、チューニングは一切されていません。
https://github.com/matarillo/isucon4/tree/master/qualifier/webapp/csharp
- Controllers
- HomeController.cs ...
Index
,Login
,MyPage
,Report
の4つのアクションを実装。ロジック自体はLogic
クラスに移譲
- HomeController.cs ...
- Infrastructure
- IDbFactory.cs ...
DbConnection
のファクトリーインターフェース - MySqlDbFactory.cs ... MySql.Data に依存した実装
- IDbFactory.cs ...
- Models
- Views
- Home ...
Index
,MyPage
のcshtmlテンプレート - Shared ... テンプレートの共通レイアウト
- Home ...
- Program.cs ... アプリケーションサーバー設定(png/cssの位置指定、ポート8080の利用)
- Startup.cs ... ASP.MVC Coreのルーティング、DIの設定など
私の環境でベンチマークを動かしてみたら、こんな感じでした。
Pythonの参考実装だとこんな感じ。
ほぼ差がありません。
アプリケーションに手を入れるとしたら、データアクセスが中心でしょうね。