内存溢出:越来越多的 Microsoft.CSharp.RuntimeBinder.Semantics [英] Memory Overflow: Having an increasing number of Microsoft.CSharp.RuntimeBinder.Semantics

查看:47
本文介绍了内存溢出:越来越多的 Microsoft.CSharp.RuntimeBinder.Semantics的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

不幸的是,我不知道这是什么,所以我很难找到我应该如何/应该发布什么.

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

问题在于,当我们对项目进行打开/关闭"时,我们会浏览大量(大部分)代码.

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

编辑 2

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

解决方案

我今天通过分析应用程序中的内存泄漏遇到了完全相同的问题

康桥

为了解决这个问题,我写了一点

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

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

We are currently hunting some memory leaks in our application, when doing some operation(loading and closing one project inside our application), we know that the memory increase always a little bit.

We have already found a lot of them, but now, the 10+ most increasing classes are (according to our tool, 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

Unfortunately, I don't what this is, so It's a little bit hard for me to find how/what I should release.

I checked the instance tree but, it goes all the way with microsoft stuff.

The issue is that when we do the "Open/close" of a project, we go through a lot(most of) our code.

EDIT One part of our application uses the dynamic keyword for some resources, it may be linked. The class here are not Disposable, should I do something special with them?

EDIT 2

I'm pretty sure this is related to my dynamic stuff, it seems that C# create a cache when using dynamic. But currently I've no idea why it grows(I load the same classes all the time, and I will have exactly the same signature all the time), nor how to clear this.

解决方案

I encountered exactly the same issue today by profiling memory leaks in my app RepoZ. That tool is supposed to run in the background, checking Git repositories and update Windows Explorer window titles periodically. The latter task has to make some COM calls to "Shell.Application" to find the Explorer windows and determine the path they are currently pointing to.

By using the dynamic keyword like this ...

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

... I ended up to a memory dump like that after a few hours:

Combridge

To solve that, I wrote a little helper class called "Combridge" caring to release COM objects and providing quite easy access to methods and properties of the underlying COM object. It is very easy and straightforward, nothing special here. It makes use of Reflection to COM objects, that's why there's some loss in performance (see below).

With it, the code sample from above looks like this:

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

You can see the file ExplorerWindowActor on how it is used in RepoZ.

It is not exactly as beautiful as with dynamic and performance got worse in this first attempt as well. A quick bench showed the following:

Performance

I tested 1000 iterations, in each iteration 10 open Explorer windows were processed. For each window, 4 methods or properties are invoked on that COM object. So we're talking about 40.000 COM calls.

The duration went up from ~2500ms (dynamic) to ~6000ms (Combridge). That's from 0.062ms to 0.150ms for each call.

So this takes about 2.4x the time to finish now.

This is significant, I know. But it is okay for my requirements and the memory leak is gone.

That's it - I wanted to share that story with you, hopefully you can use that class (or an improved version of it) to get out of the dynamic hell as well.

~Update~

After 10 hours, RepoZ still runs with a very constant memory footprint.

So with 10 Explorer windows open, 4 COM calls per window and that whole loop two times a second, RepoZ created about 72.000 COM instances and made about 2.880.000 COM calls in total without any increase in memory consumption.

I guess we can say that the issue really comes with dynamic.

这篇关于内存溢出:越来越多的 Microsoft.CSharp.RuntimeBinder.Semantics的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆