gpt4 book ai didi

c# - 内存溢出 : Having an increasing number of Microsoft. CSharp.RuntimeBinder.Semantics

转载 作者:可可西里 更新时间:2023-11-01 08:48:14 24 4
gpt4 key购买 nike

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

我们已经找到了很多,但现在,增加最多的 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

不幸的是,我不知道这是什么,所以我很难找到我应该发布的方式/发布的内容。

我检查了实例树,但它与微软的东西一路走来。

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

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

编辑 2

我很确定这与我的dynamic 相关,似乎 C# 在使用 dynamic 时创建了一个缓存。但目前我不知道它为什么会增长(我一直加载相同的类,并且我将一直拥有完全相同的签名),也不知道如何清除它。

最佳答案

我今天在我的应用程序中分析内存泄漏时遇到了完全相同的问题 RepoZ .该工具应该在后台运行,检查 Git 存储库并定期更新 Windows 资源管理器窗口标题。后一项任务必须对“Shell.Application”进行一些 COM 调用,以找到资源管理器窗口并确定它们当前指向的路径。

像这样使用dynamic关键字...

dynamic shell = Activator.CreateInstance(...);
foreach (object window in shell.Windows())
{
var hwnd = window.Hwnd;
...
}

...几个小时后,我最终遇到了这样的内存转储:

enter image description here

康桥

为了解决这个问题,我写了一点 helper class called "Combridge"关心释放 COM 对象并提供对底层 COM 对象的方法和属性的相当容易的访问。这非常简单明了,这里没有什么特别的。它利用 Reflection to COM objects ,这就是性能有所下降的原因(见下文)。

有了它,上面的代码示例如下所示:

using (var shell = new Combridge(Activator.CreateInstance(...)))
{
var windows = shell.InvokeMethod<IEnumerable>("Windows");
foreach (var window in windows)
{
var hwnd = window.GetPropertyValue<long>("Hwnd");
...
}
}

可以看到文件ExplorerWindowActor关于如何在 RepoZ 中使用它。

它并不像 dynamic 那样漂亮,而且在第一次尝试中性能也变差了。快速工作台显示如下:

性能

我测试了 1000 次迭代,在每次迭代中处理了 10 个打开的资源管理器窗口。对于每个窗口,在该 COM 对象上调用 4 个方法或属性。所以我们谈论的是 40.000 个 COM 调用。

持续时间从约 2500 毫秒(动态)增加到约 6000 毫秒(Combridge)。每次调用的时间从 0.062 毫秒到 0.150 毫秒不等。

所以这需要大约 2.4 倍的时间才能完成。

这很重要,我知道。但这对我的要求来说没问题,内存泄漏也没有了。

就是这样 - 我想与您分享这个故事,希望您也可以使用该类(或它的改进版本)摆脱动态 hell 。

~更新~

10 小时后,RepoZ 仍然以非常稳定的内存占用运行。

enter image description here

因此,在打开 10 个资源管理器窗口、每个窗口 4 个 COM 调用并且整个循环每秒两次的情况下,RepoZ 创建了大约 72.000 个 COM 实例,并进行了大约 2.880.000 个 COM 调用 总体上没有任何内存消耗的增加。

我想我们可以说问题确实来自 dynamic

关于c# - 内存溢出 : Having an increasing number of Microsoft. CSharp.RuntimeBinder.Semantics,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33080252/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com