解释一下 static readonly ConcurrentDictionary<string, AsyncLocal<object>> 状态是否泄漏内存?
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>
会发生什么情况的本质?我看到它在内存中徘徊,但无法判断它是否是内存泄漏,或者 ig GC 还没有回收它。
我知道静态字典仍然存在,但也保留值,或者我是否需要在当前服务调用完成之前手动清除这些值以确保此处没有内存泄漏?
*编辑 - 这是 Pavel 要求的更多信息。
下面贴出相关代码,但全图在这里。
Github 一般想法来自哪里。他们正试图让 headers 在 ServiceFabric/.net 核心中工作,就像他们以前在旧 WCF 中一样。
https://github.com/Expecho/ServiceFabric-Remoting-CustomHeaders
RemotingContext object 在这里:
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 覆盖异步任务 HandleRequestResponseAsync(IServiceRemotingRequestContext requestContext,
IServiceRemotingRequestMessage 请求消息)
{
var header = requestMessage.GetHeader();</p>
<pre><code> 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 是静态的,因此它始终存在,因此其中包含的任何内容都将始终具有对它的引用。如果没有对包含对象的其他引用,并且您将其从字典中删除,它将变得不可访问,因此将成为垃圾并被收集。确保没有对您的对象的引用是确保它们被收集的方法。很容易忘记您在某处所做的一些引用,这些引用使对象保持活动状态。
其次,垃圾收集器不会持续 运行。它 运行s 当内存资源越来越低并且需要释放一些内存时。这样它就不会占用 CPU 而损害主要应用程序。这意味着在下一次垃圾收集之前,对象仍可以在内存中保留一段时间。这有时会使内存使用率看起来很高,即使实际上并非如此。
第三,垃圾收集器有“世代”。第 0 代对象是最新和最短寿命的对象。第 0 代对象最常被收集,但仅在需要内存时才收集。
第 1 代包含即将成为长寿命对象的短寿命对象。与第 0 代对象相比,它们的收集频率较低。事实上,只有第 0 代回收没有释放足够的内存时,才会发生第 1 代回收。
第 2 代对象是长期存在的。这些通常是在应用程序的生命周期内存在的静态对象之类的东西。同样,当第 1 代收集没有释放足够的内存时,这些也会被收集。
最后是大对象堆。消耗大量内存的对象需要时间来回移动(垃圾收集过程的一部分涉及在收集发生后对内存进行碎片整理),因此除非收集没有释放足够的内存,否则它们往往不会被收集。有人说这是第3代,其实必要的时候会收在第2代。
我有一个应用程序似乎积累了很多内存。 其中一名嫌疑犯在下面,我只是想了解它实际在做什么。或者,更具体地说,它是如何清理的?
private static readonly ConcurrentDictionary<string, AsyncLocal<object>> State;
问题背景:
这个想法是模拟 WCF 中的 OperationContext
会做什么 - 提供对有关当前调用的信息的静态访问。我正在 Service Fabric 远程服务中执行此操作。
谁能帮助我理解异步调用结束后 AsyncLocal<object>
会发生什么情况的本质?我看到它在内存中徘徊,但无法判断它是否是内存泄漏,或者 ig GC 还没有回收它。
我知道静态字典仍然存在,但也保留值,或者我是否需要在当前服务调用完成之前手动清除这些值以确保此处没有内存泄漏?
*编辑 - 这是 Pavel 要求的更多信息。
下面贴出相关代码,但全图在这里。 Github 一般想法来自哪里。他们正试图让 headers 在 ServiceFabric/.net 核心中工作,就像他们以前在旧 WCF 中一样。 https://github.com/Expecho/ServiceFabric-Remoting-CustomHeaders
RemotingContext object 在这里: 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 覆盖异步任务 HandleRequestResponseAsync(IServiceRemotingRequestContext requestContext,
IServiceRemotingRequestMessage 请求消息)
{
var header = requestMessage.GetHeader();</p>
<pre><code> 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 是静态的,因此它始终存在,因此其中包含的任何内容都将始终具有对它的引用。如果没有对包含对象的其他引用,并且您将其从字典中删除,它将变得不可访问,因此将成为垃圾并被收集。确保没有对您的对象的引用是确保它们被收集的方法。很容易忘记您在某处所做的一些引用,这些引用使对象保持活动状态。
其次,垃圾收集器不会持续 运行。它 运行s 当内存资源越来越低并且需要释放一些内存时。这样它就不会占用 CPU 而损害主要应用程序。这意味着在下一次垃圾收集之前,对象仍可以在内存中保留一段时间。这有时会使内存使用率看起来很高,即使实际上并非如此。
第三,垃圾收集器有“世代”。第 0 代对象是最新和最短寿命的对象。第 0 代对象最常被收集,但仅在需要内存时才收集。
第 1 代包含即将成为长寿命对象的短寿命对象。与第 0 代对象相比,它们的收集频率较低。事实上,只有第 0 代回收没有释放足够的内存时,才会发生第 1 代回收。
第 2 代对象是长期存在的。这些通常是在应用程序的生命周期内存在的静态对象之类的东西。同样,当第 1 代收集没有释放足够的内存时,这些也会被收集。
最后是大对象堆。消耗大量内存的对象需要时间来回移动(垃圾收集过程的一部分涉及在收集发生后对内存进行碎片整理),因此除非收集没有释放足够的内存,否则它们往往不会被收集。有人说这是第3代,其实必要的时候会收在第2代。