C# 达到内存限制会降低.Net应用程序的速度

C# 达到内存限制会降低.Net应用程序的速度,c#,.net,performance,memory-management,C#,.net,Performance,Memory Management,我们有一个运行在64位Windows服务器上的64位C#/.Net3.0应用程序。该应用程序有时可以使用大量可用内存。在某些情况下,应用程序停止分配额外的内存并显著降低速度(慢500多倍)。当我从任务管理器检查内存时,使用的内存量几乎没有变化。该应用程序一直运行得非常慢,并且从未出现内存不足异常。 有什么想法吗?如果需要更多数据,请告诉我 当您达到物理内存限制时,操作系统将开始分页(即,将内存写入磁盘)。这确实会导致你所看到的那种减速 解决方案 添加更多内存-这只会在您达到新的内存限制之前有所

我们有一个运行在64位Windows服务器上的64位C#/.Net3.0应用程序。该应用程序有时可以使用大量可用内存。在某些情况下,应用程序停止分配额外的内存并显著降低速度(慢500多倍)。当我从任务管理器检查内存时,使用的内存量几乎没有变化。该应用程序一直运行得非常慢,并且从未出现内存不足异常。
有什么想法吗?如果需要更多数据,请告诉我

当您达到物理内存限制时,操作系统将开始分页(即,将内存写入磁盘)。这确实会导致你所看到的那种减速

解决方案

  • 添加更多内存-这只会在您达到新的内存限制之前有所帮助
  • 重写应用程序以使用更少的内存
  • 找出是否存在内存泄漏并修复它
如果内存不是问题,那么您的应用程序对CPU的影响可能很大?你看到CPU接近100%了吗?如果是这样,请检查正在反复迭代的大型集合。

(MSDN文章)

你可以试试。默认情况下,所有.NET应用程序都在工作站模式下运行,GC在保持应用程序运行的同时尝试进行扫描。如果打开服务器模式,它会暂时停止应用程序,以便更快地释放内存,并且它还会对每个处理器/核心使用不同的堆

大多数服务器应用程序将看到使用GC服务器模式的性能改进,特别是在分配大量内存的情况下。缺点是,当你的应用程序开始耗尽内存时(直到GC完成),它基本上会停止运行

*要启用此模式,请将以下内容插入
app.config
web.config

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

其他答案中提到了很多好东西。不过,无论如何,我还是要拿出我的两便士(或美分——取决于你来自哪里!)

假设这确实是一个64位进程,如您所述,这里有一些调查方法

您正在检查哪种内存使用情况?内存使用还是VMem大小?VMem大小实际上很重要,因为它适用于分页和非分页内存。如果这两个数字相差甚远,那么内存使用确实是导致速度减慢的原因

当事情开始变慢时,整个服务器的实际内存使用量是多少?减速是否也适用于其他应用程序?如果是这样,那么可能会出现内核内存问题—这可能是由于大量磁盘访问和低级别资源使用(例如,创建20000个互斥锁,或通过使用Win32 HBitmaps的代码加载数千个位图)。您可以在任务管理器上看到一些这方面的指示(尽管Windows 2003的版本比2008的版本更能直接提供这方面的信息)

当你说应用程序速度明显变慢时,你怎么知道?你在使用大量的字典或列表吗?难道这不仅仅是因为内部数据结构变得如此庞大,以至于使任何内部算法执行的工作变得复杂吗?当你得到一个巨大的数字时,一些算法可能会开始变慢几个数量级

应用程序在满负荷运行时的CPU负载是多少?实际上与减速发生时相同吗?如果CPU使用量随着内存使用量的增加而减少,那么这意味着无论它做什么都需要操作系统更长的时间才能完成,这意味着它可能会给操作系统带来太多的负载。如果CPU负载没有差别,那么我猜是内部数据结构变得太大,以至于减慢了算法的速度


我当然会考虑在应用程序上运行Perfmon—从一些.Net和本机内存计数器、缓存命中和未命中以及磁盘队列长度开始。在应用程序从启动到开始像哮喘龟一样运行的整个过程中运行它,您可能也会从中得到一些线索。

浏览了其他答案后,我想说有很多好主意。这里有一个我没有看到:

获取一个内存分析器,比如SciTech的MemProfiler。它会告诉你被分配的是什么,由什么分配,它会显示整个切片n骰子


它也有视频教程,以防你不知道如何使用它。在我的例子中,我发现我有我没有使用的IDisposable实例(…)

检查垃圾收集器是否正在运行…检查CPU温度是否过高从问题中可以看出有足够的物理内存可用,但应用程序出于某种原因没有使用它…不,cpu没有得到充分利用,一台机器使用2.8-3GB的8GB内存,另一台机器使用7-8GB的16GB内存。OP声明了64位操作系统和64位应用程序。限制仍然适用。。。“…在64位Windows操作系统上运行64位托管应用程序时。”在某些方面,限制更为严格,因为64位应用程序中的引用需要8个字节,而32位仅需要4个字节。。。换句话说,64位应用程序中的引用数只有32位应用程序的1/2……我们没有那么大的对象。我们只是有很多。我们创建和处理许多小对象(double数组),我很难找到如何在web上为垃圾收集器设置服务器模式。如果你知道你能把它添加到答案中吗?@derdo:链接中已经解释过了,但我在这个答案中重印了它。GC服务器模式对我们帮助很大。此外,我们还通过探查器确定了每秒分配大量GB内存的位置。我们在这方面也做了一些改进,最终解决了这个问题。谢谢大家的回复。