मैं एक व्यापार मंच परियोजना के लिए आरएक्स का मूल्यांकन कर रहा हूं जिसे हजारों संदेशों को एक सेकंड में संसाधित करने की आवश्यकता होगी। मौजूदा प्लेटफ़ॉर्म में एक जटिल ईवेंट रूटिंग सिस्टम (मल्टीकास्ट प्रतिनिधि) है जो इन संदेशों का जवाब देता है और बाद में प्रसंस्करण करता है।प्रतिक्रियाशील एक्सटेंशन बहुत धीमे लगते हैं - क्या मैं कुछ गलत कर रहा हूं?
मैंने स्पष्ट लाभों के लिए प्रतिक्रियाशील एक्सटेंशन को देखा है लेकिन ध्यान दिया है कि यह कुछ हद तक धीमा, सामान्य 100 गुना धीमा है।
मैंने यह दिखाने के लिए इकाई परीक्षण बनाया है जो विभिन्न आरएक्स स्वादों और सीधे-बाहर-द-बॉक्स प्रतिनिधि "नियंत्रण" परीक्षण का उपयोग करके 1 मिलियन बार सरल वृद्धि करता है।
Delegate - (1000000) - 00:00:00.0410000
Observable.Range() - (1000000) - 00:00:04.8760000
Subject.Subscribe() - NewThread - (1000000) - 00:00:02.7630000
Subject.Subscribe() - CurrentThread - (1000000) - 00:00:03.0280000
Subject.Subscribe() - Immediate - (1000000) - 00:00:03.0030000
Subject.Subscribe() - ThreadPool - (1000000) - 00:00:02.9800000
Subject.Subscribe() - Dispatcher - (1000000) - 00:00:03.0360000
आप देख सकते हैं, सभी आरएक्स तरीकों ~ 100 बार एक प्रतिनिधि बराबर की तुलना में धीमी कर रहे हैं:
यहाँ के परिणाम हैं। स्पष्ट रूप से आरएक्स कवर के तहत बहुत कुछ कर रहा है जो अधिक जटिल उदाहरण में उपयोग किया जाएगा, लेकिन यह अविश्वसनीय रूप से धीमा लगता है।
क्या यह सामान्य है या मेरी परीक्षण धारणाएं अमान्य हैं? नीचे से ऊपर के लिए Nunit कोड -
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.Concurrency;
namespace RxTests
{
[TestFixture]
class ReactiveExtensionsBenchmark_Tests
{
private int counter = 0;
[Test]
public void ReactiveExtensionsPerformanceComparisons()
{
int iterations = 1000000;
Action<int> a = (i) => { counter++; };
DelegateSmokeTest(iterations, a);
ObservableRangeTest(iterations, a);
SubjectSubscribeTest(iterations, a, Scheduler.NewThread, "NewThread");
SubjectSubscribeTest(iterations, a, Scheduler.CurrentThread, "CurrentThread");
SubjectSubscribeTest(iterations, a, Scheduler.Immediate, "Immediate");
SubjectSubscribeTest(iterations, a, Scheduler.ThreadPool, "ThreadPool");
SubjectSubscribeTest(iterations, a, Scheduler.Dispatcher, "Dispatcher");
}
public void ObservableRangeTest(int iterations, Action<int> action)
{
counter = 0;
long start = DateTime.Now.Ticks;
Observable.Range(0, iterations).Subscribe(action);
OutputTestDuration("Observable.Range()", start);
}
public void SubjectSubscribeTest(int iterations, Action<int> action, IScheduler scheduler, string mode)
{
counter = 0;
var eventSubject = new Subject<int>();
var events = eventSubject.SubscribeOn(scheduler); //edited - thanks dtb
events.Subscribe(action);
long start = DateTime.Now.Ticks;
Enumerable.Range(0, iterations).ToList().ForEach
(
a => eventSubject.OnNext(1)
);
OutputTestDuration("Subject.Subscribe() - " + mode, start);
}
public void DelegateSmokeTest(int iterations, Action<int> action)
{
counter = 0;
long start = DateTime.Now.Ticks;
Enumerable.Range(0, iterations).ToList().ForEach
(
a => action(1)
);
OutputTestDuration("Delegate", start);
}
/// <summary>
/// Output helper
/// </summary>
/// <param name="test"></param>
/// <param name="duration"></param>
public void OutputTestDuration(string test, long duration)
{
Debug.WriteLine(string.Format("{0, -40} - ({1}) - {2}", test, counter, ElapsedDuration(duration)));
}
/// <summary>
/// Test timing helper
/// </summary>
/// <param name="elapsedTicks"></param>
/// <returns></returns>
public string ElapsedDuration(long elapsedTicks)
{
return new TimeSpan(DateTime.Now.Ticks - elapsedTicks).ToString();
}
}
}
विषय सदस्यता सबस्टाइल 'शेड्यूलर' तर्क का उपयोग नहीं करता है, इसलिए मुझे आश्चर्य है कि आपको वास्तव में अलग-अलग परिणाम मिलते हैं। – dtb
और आप सीधे पर्यवेक्षण में कार्रवाई की सदस्यता लेने के बजाय किसी विषय का उपयोग क्यों कर रहे हैं? अफैइक विषय कवर के तहत काफी कुछ करते हैं, इसलिए आपको यह जांचना चाहिए कि इसे हटाने से कोई फर्क पड़ता है या नहीं। – dtb
मुझे आश्चर्य है कि ObservableRangeTest * वास्तव में * खराब प्रदर्शन करता है, यहां तक कि विषय के साथ परीक्षणों की तुलना में भी। WTF? – dtb