.NET 4.0 中非常高的内存使用率 [英] Very High Memory Usage in .NET 4.0

查看:35
本文介绍了.NET 4.0 中非常高的内存使用率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 C# Windows 服务,我最近从 .NET 3.5 转移到了 .NET 4.0.没有进行其他代码更改.

I have a C# Windows Service that I recently moved from .NET 3.5 to .NET 4.0. No other code changes were made.

在 3.5 上运行时,给定工作负载的内存利用率约为 1.5 GB 内存,吞吐量为每秒 20 倍.(在这个问题的上下文中,X 无关紧要.)

When running on 3.5, memory utilzation for a given work load was roughly 1.5 GB of memory and throughput was 20 X per second. (The X doesn't matter in the context of this question.)

在 4.0 上运行的完全相同的服务使用 3GB 到 5GB+ 的内存,每秒不到 4 X.事实上,随着内存使用量不断攀升,该服务通常最终会停止运行,直到我的系统处于 99% 的利用率并且页面文件交换变得疯狂.

The exact same service running on 4.0 uses between 3GB and 5GB+ of memory, and gets less than 4 X per second. In fact, the service will typically end up stalling out as memory usage continue to climb until my system is siting at 99% utilization and page file swapping goes nuts.

我不确定这是否与垃圾收集有关,还是什么,但我无法弄清楚.我的窗口服务通过如下所示的配置文件开关使用服务器"GC:

I'm not sure if this has to do with garbage collection, or what, but I'm having trouble figuring it out. My window service uses the "Server" GC via the config file switch seen below:

  <runtime>
    <gcServer enabled="true"/>
  </runtime>

将此选项更改为 false 似乎没有什么区别.此外,从我在 4.0 中对新 GC 所做的阅读来看,大的变化只影响工作站 GC 模式,而不是服务器 GC 模式.所以也许GC与这个问题无关.

Changing this option to false didn't seem to make a difference. Futhermore, from the reading I've done on the new GC in 4.0, the big changes only effect the workstation GC mode, not server GC mode. So perhaps GC has nothing to do with the issue.

想法?

推荐答案

嗯,这是一个有趣的方案.

Well this was an interesting one.

事实证明,根本原因是在 .NET 4.0 之上运行 SQL Server Reporting Services 的 LocalReport 类 (v2010) 的行为发生了变化.

The root cause turns out to be a change in the behavior of SQL Server Reporting Services' LocalReport class (v2010) when running this on top of .NET 4.0.

基本上,Microsoft 更改了 RDLC 处理的行为,以便每次处理报告时都在单独的应用程序域中进行.这实际上是为了解决由于无法从应用程序域卸载程序集而导致的内存泄漏.当 LocalReport 类处理 RDLC 文件时,它实际上会动态创建一个程序集并将其加载到应用程序域中.

Basically, Microsoft altered the behavior of RDLC processing so that each time a report was processed it was done so in a seperate application domain. This was actually done specifically to address a memory leak caused by the inability to unload assemblies from app domains. When the LocalReport class processed an RDLC file, it actually creates an assembly on the fly and loads it into the app domain.

就我而言,由于我正在处理大量报告,这导致创建了大量 System.Runtime.Remoting.ServerIdentity 对象.这是我对原因的提示,因为我对为什么处理 RLDC 需要远程处理感到困惑.

In my case, due to the large volume of report I was processing, this was resulting in very large numbers of System.Runtime.Remoting.ServerIdentity objects being created. This was my tip off to the cause, as I was confused as to why processing an RLDC required remoting.

当然,要调用另一个应用程序域中的类的方法,远程处理正是您使用的.在 .NET 3.5 中,这不是必需的,因为默认情况下,RDLC 程序集已加载到同一个应用程序域中.但是,在 .NET 4.0 中,默认情况下会创建一个新的应用程序域.

Of course, to call a method on a class in another app domain, remoting is exactly what you use. In .NET 3.5, this wasn't necessary as, by default, the RDLC-assembly was loaded into the same app domain. In .NET 4.0, however, a new app domain is created by default.

修复相当简单.首先,我需要使用以下配置启用旧安全策略:

The fix was fairly easy. First I needed to go enable legacy security policy using the following config:

  <runtime>
    <NetFx40_LegacySecurityPolicy enabled="true"/>
  </runtime>

接下来,我需要通过调用以下命令来强制在与我的服务相同的应用域中处理 RDLC:

Next, I needed to force the RDLCs to be processed in the same app domain as my service by calling the following:

myLocalReport.ExecuteReportInCurrentAppDomain(AppDomain.CurrentDomain.Evidence);

这解决了问题.

这篇关于.NET 4.0 中非常高的内存使用率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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