2013-06-01 22 views
1

我正在使用rx distinct操作符來過濾長時間運行的進程中基於某個鍵的外部數據流。建議在長時間運行的過程中使用rx獨特功能?

這會導致內存泄漏嗎?假設會收到很多不同的密鑰。 rx獨特的操作員如何跟蹤之前收到的密鑰?

我應該使用groupbyuntil而不是持續時間選擇器嗎?

+2

儘管3D-Grabber的答案(這是一個很好的答案),但請不要忽視這些明顯的問題,並且不要使用內存分析器測試您的代碼。無論如何,如果你擔心內存泄漏,你應該這樣做。如果你已經考慮到了這一點,我很抱歉,但是我經常發現人們會在關於可能的API泄漏的時候着迷,這時用分析器幾分鐘就會證明API是好的*並且*在他們自己的代碼中發現漏洞。 :)至少,您可以衡量您特定場景的特徵。 –

+0

感謝詹姆斯,我接受了你的建議,並且確實我們確實有內存泄漏在不同的密鑰上,通過在長時間運行的訂閱上使用不同的運算符。然後我們改變了使用關閉持續時間選擇器的分組,直到解決了內存泄漏問題。 – Misterhex

回答

4

Observable.Distinct內部使用HashSet。內存使用量將大致與所遇到的不同Keys的數量成比例。 (AFAIK大約30 * n字節)

GroupByUntil做了一些與Distinct完全不同的事情。
GroupByUntil(well)groups,而Distinct過濾流的元素。

不能確定的用途,但如果你只是要過濾連續相同的元素,你需要Observable.DistinctUntilChanged具有內存佔用獨立按鍵的數量。

+0

HashSet,而不是HashMap。在HashSet中,所有密鑰都是唯一的。 「對於非常大的HashSet 對象,可以通過在運行時環境中將gcAllowVeryLargeObjects配置元素的啓用屬性設置爲true,將64位系統上的最大容量增加到20億個元素。」 –

+0

_HashSet,而不是HashMap_ => 固定的thx被困在Java世界中 – 3dGrabber

1

這可能是一個有爭議的策略,但是如果您擔心不同的密鑰會累積,並且如果某個時間點可以安全地重置,那麼可以使用Observable.Switch引入重置策略。例如,我們有一個每天都會重置「世界狀態」的場景,所以我們可以每天重置不同的可觀察項。

Observable.Create<MyPoco>(
    observer => 
    { 
     var distinctPocos = new BehaviorSubject<IObservable<MyPoco>>(pocos.Distinct(x => x.Id)); 

     var timerSubscription = 
      Observable.Timer(
       new DateTimeOffset(DateTime.UtcNow.Date.AddDays(1)), 
       TimeSpan.FromDays(1), 
       schedulerService.Default).Subscribe(
        t => 
        { 
         Log.Info("Daily reset - resetting distinct subscription."); 
         distinctPocos.OnNext(pocos.Distinct(x => x.Id)); 
        }); 

     var pocoSubscription = distinctPocos.Switch().Subscribe(observer); 

     return new CompositeDisposable(timerSubscription, pocoSubscription); 
    }); 

不過,我傾向於與上面一個內存分析器關於測試詹姆斯世界的評論同意檢查內存的確是一個問題,可能引入不必要的複雜性了。如果您將32位整數作爲關鍵字,則在大多數平臺上遇到內存問題之前,您將擁有數百萬個獨特的項目。例如。 262144 32位int鍵將佔用1兆字節。這可能是因爲你在這個時間很久之前重置了這個過程,這取決於你的情況。