C# 内存溢出:Microsoft.CSharp.RuntimeBinder.Semantics的数量不断增加

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

我们目前正在查找应用程序中的一些内存泄漏,在执行某些操作(加载并关闭应用程序中的一个项目)时,我们知道内存总是有一点增加

我们已经找到了很多,但是现在,增加最多的10+类是(根据我们的工具ANTS Memory Profiler 8.2):

  • 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
不幸的是,我不知道这是什么,所以我很难找到我应该如何/发布什么

我检查了实例树,但它与microsoft的东西完全一致

问题是,当我们对一个项目进行“打开/关闭”时,我们会检查很多(大部分)代码

编辑我们的应用程序的一部分使用了
动态
关键字作为某些资源,它可能是链接的。这里的班级不是一次性的,我应该对他们做些特别的事情吗

编辑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吗?您能在应用程序中找到一个代码片段吗