2013-05-21 16 views
6

私は、ReactiveUIを使用している.NET 3.5アプリケーションで、ObservableAsPropertyHelperに由来すると思われる重要なメモリリークがあることに気付きました。私はそれを実証するためのテストプロジェクトを作成したhereReactiveUI ObservableAsPropertyHelper/Reactive Extensionsメモリリーク?

単純なObservableAsPropertyHelper計算プロパティによってトリガされるすべての変更通知はメモリをリークするようです。このリークは、ReactiveUIで直接発生するのではなくReactive Extensionsで発生したようですが、OAPHの使用は非常に簡単なので、誰かがこれに遭遇したかどうか、あるいは修正案があるかもしれません。

メモリリークの重大度は、.NET 3.5(RxUI 2.4、Rx 1.1)と.NET 4.0(RxUI 4.2、Rx 2.0.3)の間で異なります。これは、.NET 3.5のプロパティのすべての更新で線形に非常に近いです。しかし、リークはまだ.NET 4.0に残っています。

テストアプリケーションと、.NET 3.5および.NET 4.0テストセッション用のいくつかのプロファイライメージを、テストアプリケーションhereと一緒にアップロードしました。

オブジェクトのグラフが異なっていることがイメージでわかるので、2つの異なるリークについて完全に話しているかもしれません。 4.0セッション(40_RetentionGraph.png)では、最も割り当てられたオブジェクトがInts(私のOAPHプロパティの型)とConcurrentQueueであることが分かります。そこには何らかの循環参照の問題があるようです。また、40_IntsAllocatedGCRootGrows.pngに、インスタンスのGCルートからの距離が広がっていることがわかります。

3.5バージョン(私が最も心配している)では、最も割り当てられたオブジェクトがActionおよびScheduledObserverであることがわかります(35_Summary.png)。オブジェクトグラフは、もう少し複雑で40バージョンとはまったく異なります。

私はthis discussionを見直しましたが、直接の回答は見つかりませんでした。私のシナリオは、OAPHの非常に簡単なアップデートです。このリークの可能な解決策に関する洞察は高く評価されます。

答えて

4

スケジューラを指定していないため、デフォルトでRxUIはDispatcherSchedulerを使用しています。あなたのアプリはコンソールアプリケーションなので、実行中のDispatcherはありません。そのすべてのメモリはOnNextが実行するために何もせずにキューイングすることによって消費されています。

あなたは可能性がちょうどこのからReactiveTesterのコンストラクタを変更するディスパッチャを発射し、それが(WPFアプリはあなたのためと思われる)を実行するためにフレームを供給し、またはテストのために約混乱:

public ReactiveTester() 
{ 
    _Total = this.WhenAny(x => x.A, x => x.B, (a, b) => a.Value + b.Value) 
       .ToProperty(this, x => x.Total); 
} 

これまで:

public ReactiveTester() 
{ 
    _Total = this.WhenAny(x => x.A, x => x.B, (a, b) => a.Value + b.Value) 
       .ToProperty(this, x => x.Total, 0, Scheduler.CurrentThread); 
} 

すべてがバラバラです。

+0

うん、私はこれが提出されたRxUIのバグでこれを疑った。よくできました。 –

+0

これは、テストアプリの問題を解決するということです。ありがとう、ジェームスとポール!フォローアップの質問は、WPFアプリケーションで同様のリークを引き起こす可能性がある点です。私の.WhenAny()は、UIとバックグラウンドスレッドから呼び出されます。すべての.ToProperty()コールでスケジューラを明示的に指定する必要がありますか?もしそうなら、それはScheduler.CurrentThreadですか? –

+1

私はあなたのコードを見ることなく推測していますが、私はあなたの3.5サンプルがRxUIとRx 1.1を使用しているのを見ています。 IIRCを使用すると、UI以外のスレッドでToProperty()を呼び出し、スケジューラを指定しないと、その組み合わせによって新しいDispatcherが作成されます(ポンピングされません)。 Dispatcherで初期化コードを実行してみてください。 –

関連する問題