2

私はRxを初めて使用し、絶対に気に入っています。コードを使用することで大幅に簡略化できるコードの既存の部分を見つけました。私はパフォーマンスの問題に遭遇しました、そして私を助けてくれる教祖がそこにいれば本当にありがたいです。

以前は、キーフィルターとともにサブスクリプションを受け入れる手動で実装されたオブザーバークラスがありました。イベントがクラスに入ると、提供されたキーを使用して、コールバックが必要なオブザーバーを検索します。これは非常に単純化されたバージョンのコードです。

 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));
    }
 }

次のようにRxを使用するようにこれを更新しました。

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);
    }
 }

古いコードはコールバックを見つけるためにO(1)ディクショナリキールックアップを実行しますが、新しいRxコードはWhere FuncをO(n)回呼び出します。私には何千人ものオブザーバーがいます。

Rxにキーを返すFuncを与える方法はありますか?それは、内部でオブザーバーを辞書に格納するために使用できますか?パフォーマンスを向上させる別の方法はありますか?または、意図しない方法でフレームワークを使用していますか?

4

1 に答える 1

2

シーケンスを使用Publishしてオブザーバーを共有してから、を使用してソースへのサブスクリプションをよりインテリジェントに管理できます。Where'dRefCountIConnectableObservable

あなたのシナリオでは、これらの「公開された」オブザーバブルを辞書に保存し、オンデマンドで追加すると思います。

基本的な実装は次のとおりです。

class NewClass 
{ 
    private Subject<UsefulInfo> _subject = new Subject<UsefulInfo>(); 
    private IDictionary<string, IObservable<UsefulInfo>> _keyedObservables; 

    public NewClass() 
    { 
        _keyedObservables = new Dictionary<string, IObservable<UsefulInfo>>();
    } 

    IDisposable Subscribe(string key, Action<UsefulInfo> callback) 
    { 
        // NOT threadsafe for concurrent subscriptions!
        if (!_keyedObservables.Contains(key))
        {
            var keyedAndPublished = _subject.Where(x => x.Key == key)
                .Publish()
                .RefCount();

            _keyedObservables.Add(key, keyedAndPublished);
        }

        return _keyedObservables[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); 
    } 
} 
于 2012-06-22T03:03:49.133 に答える