C# 内存溢出:Microsoft.CSharp.RuntimeBinder.Semantics的数量不断增加
我们目前正在查找应用程序中的一些内存泄漏,在执行某些操作(加载并关闭应用程序中的一个项目)时,我们知道内存总是有一点增加 我们已经找到了很多,但是现在,增加最多的10+类是(根据我们的工具ANTS Memory Profiler 8.2):C# 内存溢出:Microsoft.CSharp.RuntimeBinder.Semantics的数量不断增加,c#,memory-leaks,overflow,profiler,dynamic-language-runtime,C#,Memory Leaks,Overflow,Profiler,Dynamic Language Runtime,我们目前正在查找应用程序中的一些内存泄漏,在执行某些操作(加载并关闭应用程序中的一个项目)时,我们知道内存总是有一点增加 我们已经找到了很多,但是现在,增加最多的10+类是(根据我们的工具ANTS Memory Profiler 8.2): Microsoft.CSharp.RuntimeBinder.Semantics.SYMTBL+Key Microsoft.CSharp.RuntimeBinder.Semantics.LocalVariableSymbol Microsoft.CShar
- Microsoft.CSharp.RuntimeBinder.Semantics.SYMTBL+Key
- Microsoft.CSharp.RuntimeBinder.Semantics.LocalVariableSymbol
- Microsoft.CSharp.RuntimeBinder.Semantics.CONSTVAL
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRCONSTANT
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRCLASS
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRTYPEOF
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRLIST
- Microsoft.CSharp.RuntimeBinder.Semantics.MethWithInst
- Microsoft.CSharp.RuntimeBinder.Semantics.CMemberLookupResults
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRMEMGRP
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRCALL
- Microsoft.CSharp.RuntimeBinder.Semantics.EXPRWRAP
- Microsoft.CSharp.RuntimeBinder.Semantics.AggregateDeclaration
- Microsoft.CSharp.RuntimeBinder.Semantics.Scope
动态
关键字作为某些资源,它可能是链接的。这里的班级不是一次性的,我应该对他们做些特别的事情吗
编辑2
我很确定这与我的
dynamic
相关,似乎C#在使用dynamic时创建了一个缓存。但目前我不知道它为什么会增长(我一直加载相同的类,而且我一直都会有完全相同的签名),也不知道如何清除它。动态关键字应该很少使用,因为在大多数情况下,可以找到不需要它的变通方法
根据您的应用程序,最好的建议是仔细考虑是否可以设计您的解决方案,以避免动态变化。
以下是一些动态应用程序的有效用例:
考虑到您确实需要使用dynamic,我建议您对代码进行检测,并找出哪些部分最消耗内存。
事实上,使用dynamic会增加内存消耗,因为它需要执行各种类型的操作,但要产生内存不足异常,需要对许多未知类型使用大量动态变量
在未知类型上调用方法有很多不同的方法,测量和调优瓶颈是一种方法
另外,发布一些代码片段也很有帮助 我今天在分析应用程序内存泄漏时遇到了完全相同的问题。该工具应该在后台运行,检查Git存储库并定期更新Windows资源管理器窗口标题。后一个任务必须对“Shell.Application”进行一些COM调用,以查找资源管理器窗口并确定它们当前指向的路径 通过像这样使用
dynamic
关键字
dynamic shell = Activator.CreateInstance(...);
foreach (object window in shell.Windows())
{
var hwnd = window.Hwnd;
...
}
。。。几个小时后,我的内存就这样被转储了:
康布里奇
为了解决这个问题,我写了一些文章来发布COM对象,并提供对底层COM对象的方法和属性的非常简单的访问。这是非常简单和直接的,没有什么特别的在这里。它利用了,这就是为什么会有一些性能损失(见下文)
使用它,上面的代码示例如下所示:
using (var shell = new Combridge(Activator.CreateInstance(...)))
{
var windows = shell.InvokeMethod<IEnumerable>("Windows");
foreach (var window in windows)
{
var hwnd = window.GetPropertyValue<long>("Hwnd");
...
}
}
使用(var shell=new Combridge(Activator.CreateInstance(…))
{
var windows=shell.InvokeMethod(“windows”);
foreach(windows中的var窗口)
{
var hwnd=window.GetPropertyValue(“hwnd”);
...
}
}
您可以查看关于如何在RepoZ中使用它的文件
它不如dynamic
那么漂亮,在第一次尝试中性能也变得更差。快速测试台显示以下内容:
演出
我测试了1000次迭代,每次迭代都处理10个打开的资源管理器窗口。对于每个窗口,在该COM对象上调用4个方法或属性。所以我们说的是4万个网络电话
持续时间从~2500ms(动态
)增加到~6000ms(Combridge
)。也就是说,每次通话时间从0.062ms到0.150ms不等
因此,现在完成这项工作大约需要2.4倍的时间。
我知道这很重要。但这符合我的要求,内存泄漏也消失了
就是这样-我想和你们分享这个故事,希望你们也能使用这个类(或它的改进版本)来摆脱动态地狱
~更新~
10小时后,RepoZ仍然以非常恒定的内存占用运行
因此,打开10个资源管理器窗口,每个窗口4个COM调用,整个循环每秒两次,RepoZ创建了大约72.000个COM实例,总共进行了大约2.880.000个COM调用,内存消耗没有任何增加
我想我们可以说,这个问题确实与
dynamic
有关。您对这个主题有什么发现吗?@MarChr目前没有:(我很确定这与我对dynamic
的使用有关,但我不明白为什么它会持续增长mm..似乎我也遇到了同样的问题。但这是一个巨大的应用程序,很难找出哪里出了问题。但是当我发现一些问题时,我会发布一个示例让你知道!@MarChr你有没有机会发现这样的问题lution?您真的需要使用dynamic吗?您能在应用程序中找到一个代码片段吗