簡體   English   中英

解釋是否靜態只讀 ConcurrentDictionary <string, AsyncLocal<object> &gt; 狀態泄漏內存?

[英]Explain if static readonly ConcurrentDictionary<string, AsyncLocal<object>> State leaks memory?

我有一個似乎積累了大量內存的應用程序。 嫌疑人之一在下面,我只是想弄清楚它實際上在做什么。 或者,更具體地說,它是如何清理的?

private static readonly ConcurrentDictionary<string, AsyncLocal<object>> State;

問題上下文:這個想法是模擬 WCF 中的OperationContext會做什么 - 提供對當前調用信息的靜態訪問。 我在 Service Fabric 遠程處理服務中執行此操作。

有人可以幫助我理解異步調用結束后AsyncLocal<object>會發生什么的性質嗎? 我看到它在內存中徘徊,但無法判斷它是否是內存泄漏,或者 GC 還沒有回收它。

我知道靜態字典仍然存在,但是也可以處理這些值,或者我是否需要在當前服務調用完成之前手動清除這些值以確保此處沒有內存泄漏?

*編輯 - 這是 Pavel 要求的更多信息。

在下面發布相關代碼,但整個圖片都在這里。 總體想法來自 Github。 他們試圖讓頭文件在 ServiceFabric/.net 核心中工作,就像他們在舊的 WCF 中一樣。 https://github.com/Expecho/ServiceFabric-Remoting-CustomHeaders

RemotingContext 對象在這里: https : //github.com/Expecho/ServiceFabric-Remoting-CustomHeaders/blob/master/src/ServiceFabric.Remoting.CustomHeaders/RemotingContext.cs

它的使用可以在這里看到(第 52 行等): https : //github.com/Expecho/ServiceFabric-Remoting-CustomHeaders/blob/master/src/ServiceFabric.Remoting.CustomHeaders/ReliableServices/ExtendedServiceRemotingMessageDispatcher.cs

這是一個代碼片段: public override async Task HandleRequestResponseAsync(IServiceRemotingRequestContext requestContext, IServiceRemotingRequestMessage requestMessage) { var header = requestMessage.GetHeader();

 RemotingContext.FromRemotingMessageHeader(header); //Some other code where the actual service is invoked (and where RemotingContext values can be references for the current call. return null; }

垃圾收集器是一種奇怪的野獸,因此值得了解它的行為。 (注意,這是 GC 的簡單視圖)

首先,如果一個對象只存在一個引用,則該對象不被視為垃圾,因此永遠不會被收集。 由於您的 Dictionary 是靜態的,因此它始終存在,因此其中包含的任何內容都將始終引用它。 如果對包含的對象沒有其他引用,並且您將其從字典中刪除,它將變得不可訪問,因此是垃圾並將被收集。 確保沒有對您的對象的引用是確保它們將被收集的方法。 很容易忘記您在某處所做的一些引用,這使對象保持活動狀態。

其次,垃圾收集器不會連續運行。 它在內存資源越來越低並且需要釋放一些內存時運行。 這樣就不會占用 CPU 從而損害主要應用程序。 這意味着在下一次垃圾收集之前,對象仍然可以在內存中存在一段時間。 這有時會使內存使用量看起來很高,即使實際上並非如此。

第三,垃圾收集器有“世代”。 第 0 代對象是最新和最短暫的對象。 最常收集第 0 代對象,但僅在需要內存時才收集。

第 1 代包含正在成為長期對象的短期對象。 它們的收集頻率低於第 0 代對象。 事實上,第 1 代回收僅在第 0 代回收沒有釋放足夠內存時才會發生。

第 2 代對象是長期存在的。 這些通常是在應用程序的生命周期中存在的靜態對象。 類似地,當第 1 代集合沒有釋放足夠的內存時,這些會被收集。

最后,還有大對象堆。 消耗大量內存的對象需要時間來移動(垃圾收集過程的一部分涉及在收集發生后對內存進行碎片整理),因此除非收集沒有釋放足夠的內存,否則它們往往保持未收集狀態。 有些人把這稱為第三代,但實際上是在必要時在第二代中收集的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM