I'm new to Rx and am absolutely loving it. I've found existing parts of our code that can be greatly simplified by using it. I've run into a performance issue and would be really grateful if there's a guru out there who could help me please.
Previously I had a manually implemented observer class that accepted subscriptions along with a key filter. When an event came into the class, it would use the key provided to look up which observers needed a callback. This is a very simplified version of the code:
class OldClass
{
private Dictionary<string, List<Action<UsefulInfo>> _callbacks =
new Dictionary<string, List<Action<UsefulInfo>>();
void Subscribe(string key, Action<UsefulInfo> callback)
{
_callbacks[key].Add(callback);
}
// Some event happens that we want to notify subscribers about
void EventHandler(object sender, SomeEventArgs e)
{
// Create object for callbacks
UsefulInfo info = CreateUsefulInfo(e);
string key = info.Key;
// Look up callbacks for key
_callbacks[key].ForEach(callback => callback(info));
}
}
I've updated this to use Rx as follows:
class NewClass
{
private Subject<UsefulInfo> _subject = new Subject<UsefulInfo>();
private IObservable<UsefulInfo> _observable;
public NewClass()
{
_observable = _subject.ToObservable();
}
IDisposable Subscribe(string key, Action<UsefulInfo> callback)
{
return _observable.Where(x => x.Key == key).Subscribe(callback);
}
// Some event happens that we want to notify subscribers about
void EventHandler(object sender, SomeEventArgs e)
{
UsefulInfo info = CreateUsefulInfo(e);
_observable.OnNext(info);
}
}
The old code does an O(1) dictionary key look-up to find the callbacks, but the new Rx code calls the Where Func O(n) times. I have thousands of observers.
Is there a way I can give Rx a Func that returns a key which it can then use internally to store the observer in a dictionary? Is there another way I could improve performance? Or am I using the framework in a way that was not intended?