ということで、昨年のクリスマスイブのid:neueccさんの記事を読んで気になったので試してみました。
記事の締めくくりに下記のように書いてあります。
注意しないといけないのは、ふつーのシーケンスがあって、それをRxで分配やるとはっきし言って遅いです。 列挙数が多くなると、ただ配列舐めるのに比べて数万倍のパフォーマンス差が出たりします。
ということで、ざくっと以下のようなコードを書いてみました。もちろんneueccさんの記事にある通り、このケースがRxに向かないのは承知の上で書いてます。
namespace ConsoleApplication5 { using System; using System.Diagnostics; using System.Linq; using System.Reactive.Linq; class Program { static void Main(string[] args) { var r = new Random(); // Enumerableで10万個の最小、最大、平均 Watch("Enumerable", () => { var array = Enumerable.Range(1, 1000000).Select(_ => r.Next(1000)).ToArray(); var min = array.Min(); var max = array.Max(); var avg = array.Average(); Console.WriteLine("min: {0}, max: {1}, avg: {2}", min, max, avg); }); // Observableで10万個の最小、最大、平均 Watch("Observable", () => { var o = Observable.Range(1, 1000000).Select(_ => r.Next(1000)).Publish(); o.Min().Zip(o.Max(), (min, max) => new { min, max }) .Zip(o.Average(), (x, avg) => new { x.min, x.max, avg }) .Subscribe(v => { Console.WriteLine("min: {0}, max: {1}, avg: {2}", v.min, v.max, v.avg); }); o.Connect(); }); } static void Watch(string tag, Action action) { var s = Stopwatch.StartNew(); try { action(); } finally { s.Stop(); Console.WriteLine("{0} : {1}", tag, s.ElapsedMilliseconds); } } } }
こいつを、うちのマシンで実行してみると以下の通り。
min: 0, max: 999, avg: 499.774453 Enumerable : 75 min: 0, max: 999, avg: 499.299666 Observable : 7349
100倍くらい遅いのね!!これがReactiveを手に入れるための代償なのか!まぁリアルタイムに処理をできると思えば、安いもんかな。