はじめに
heroku-buildback-mono を使えば C# で書いた WEB アプリを Heroku で動かすことができる。 ランタイムは .NET Framework じゃなくて Mono だけど。
Heroku + Mono のパフォーマンスが知りたくなったので 最小の Owin アプリケーションをデプロイして計測することにした。
コンソールアプリケーションのプロジェクトを作成
セルフホストなのでコンソールアプリケーションのプロジェクトを作成する。
NuGet パッケージを追加
NuGet パッケージマネージャーで
を追加。
Visual Studio の場合は、NuGet Package の復元を有効化しておく。 MonoDevelop(Xamarin Studio) の場合は不要だった。
最小の Owin アプリケーションを作成
using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using Owin; using Microsoft.Owin.Hosting; using Microsoft.Owin.Host.HttpListener; namespace OwinSample { using AppFunc = Func<IDictionary<string, object>, Task>; public class SampleApp { public SampleApp(AppFunc next) { } public Task Invoke(IDictionary<string, object> environment) { var stream = (Stream)environment["owin.ResponseBody"]; using (var writer = new StreamWriter (stream)) { return writer.WriteAsync ("Hello World"); } } } public class Startup { public void Configuration(IAppBuilder app) { app.Use(typeof(SampleApp)); } } class MainClass { private static readonly ManualResetEvent _quitEvent = new ManualResetEvent(false); public static void Main (string[] args) { var port = 5000; if (0 < args.Length) { int.TryParse (args [0], out port); } Console.CancelKeyPress += (sender, e) => { _quitEvent.Set(); e.Cancel = true; }; using (WebApp.Start<Startup>(string.Format("http://*:{0}", port))) { Console.WriteLine("Started"); _quitEvent.WaitOne(); } } } }
Procfile を作成
Procfile には、コンソールアプリケーションを実行するコマンドを記述する。
web: mono OwinSample.exe $PORT
ビルドするとプロジェクトルートに exe が出力されるので、mono コマンドでそいつを起動している。
Heroku にデプロイ
Heroku のユーザー登録と SSH キー登録は済んでいる前提。
$ heroku create <your-app-name> $ heroku config:add BUILDPACK_URL=https://github.com/friism/heroku-buildpack-mono $ git push heroku master
を実行し、 Mono のビルドパックを使うようにしておく。
デプロイに成功したら Webブラウザでアクセスしてみる。
Apatch Bench でベンチマーク計測
Ruby スタックと比較したいので、同じ合計リクエスト発行数と同時接続数で計測した。
合計リクエスト発行数&同時接続数 | Requests per second[#/sec] | Time per request(mean, across all concurrent requests)[ms] |
---|---|---|
-n 100 -c 100 | 29.40 | 34.015 |
-n 1000 -c 100 | 55.60 | 17.985 |
-n 1000 -c 1000 | 42.18 | 23.710 |
-n 3000 -c 1000 | 47.78 | 20.930 |
-n 2500 -c 2500 | 39.52 | 25.305 |
-n 3000 -c 2500 | 43.83 | 22.815 |
Mono スタックよりも Ruby スタックの方が性能が良かった。 今回の計測では、ともにアプリケーションサーバーを使っていないから、参考にしかならないけど。