单个.NET进程是否有内存限制?

43

我们目前正在考虑构建一个缓存系统来保存从SQL数据库中提取的数据,并使其可用于其他应用程序(网站、Web服务等)。我们设想缓存作为Windows服务运行,并基本上由一个智能字典组成,它保存缓存条目。我的问题是,应用程序的工作集是否有限制(它将在Windows Server 2003下运行)?还是物理内存量是限制?

我们目前正在考虑构建一个缓存系统,用于缓存SQL数据库中提取的数据并向其他应用程序(例如网站、Web服务等)提供访问。我们希望该缓存系统作为Windows服务运行,并使用一个智能字典来保存缓存条目。我的问题是,在Windows Server 2003下运行时,应用程序的工作集是否有限制?或者说限制仅在于物理内存量?请注意保留原文的HTML标签。

2
在编写第一行代码之前,请考虑您的缓存过期策略。这很难在以后加入。 我假设您有充分的理由想要这样做,例如离线访问。性能不是足够好的理由,因为本地机器上的内存开销可能会使性能变差。 - Sam Meldrum
实际上,性能是一个原因。第二个原因是我们想将缓存集中起来,使其可以被各种在线和离线应用程序访问。您有建立缓存系统的经验吗?您能推荐更多的阅读材料吗? - Mats
ASP.NET缓存系统可能是获取一些想法的好地方,或者也可以尝试使用缓存应用程序块:http://msdn.microsoft.com/en-us/library/cc309502.aspx - Chris S
6个回答

48

2
这与运行时版本2.0有关,但我认为在3.5中并没有改变。除非是字节数组,否则拥有一个2GB的单个对象相当不寻常 - 在您的情况下,它将是一个N大小的对象列表,所以您没问题。 - Chris S
1
限制在 .NET 4 中也是相同的。 - Sam Harwell
29
根据我的经验,尽管理论上容量为2GB,但系统在使用约1.2GB后会变得不稳定。 - Tim
7
实际上,在x86操作系统下,32位进程可以使用最高达3GB的内存,在x64操作系统下,可以使用最高达4GB的内存。请参见我的回答或访问http://msdn.microsoft.com/en-us/library/aa366778%28VS.85%29.aspx#memory_limits。 - Ohad Schneider
4
在数字应用程序中,由于数据通常是由数组支持的,而数组是.NET中的CLR对象,因此大对象限制经常会发生。在.NET 4.5中,这一限制被解除了。终于!http://www.centerspace.net/blog/large-matrices-and-vectors/ - Trevor Misfeldt
显示剩余5条评论

23

我最近在一个32位进程中进行了大量关于.NET内存限制的分析。我们都被灌输了一种观念,即在.NET应用程序中可以分配高达2.4GB(2^31)的内存,但不幸的是,这并不准确。应用程序进程只有那么多空间可供使用,操作系统为我们管理得非常好,然而,.NET本身似乎有自己的开销,典型的实际应用程序会占用约600-800MB的内存极限。这意味着,一旦你分配了一个大约需要1.4GB的整数数组,你应该预计会看到一个OutOfMemoryException()异常。

显然,在64位上,这个限制发生得更迟(让我们在5年后再聊: )),但是由于增加的字长,内存中所有东西的普遍大小也会增长(我发现它约为1.7到2倍)。

我确定的是,来自操作系统的虚拟内存概念绝对不能在一个进程内给您提供无限的内存分配空间。它只存在于所有(许多)正在运行的应用程序中,以便所有这些应用程序能够访问完整的2.4GB。


我不能确定,但根据我的测试,似乎真的是这样。 - Eric Ouellet
在我们的情况下,我们将.NET dll作为IE的插件使用。当我们使用插件时,我们还会看到IE在大约1.2 GB处抛出OOM异常。 @Luke Machowski,您能告诉我您用于.NET或IE的内存分析工具是哪个吗? - Sandeep Khantwal
@SandeepKhantwal 那是一段时间以前了,但当时我正在使用 Ants Profiler。 - Luke Machowski

19
下表来自MSDN,是对您的问题最精确的答案。请注意,尽管幸运的是可以通过editbin实用程序在构建后设置IMAGE_FILE_LARGE_ADDRESS_AWARE标志,但无法直接从托管编译器中设置该标志。4GT指的是/3gb标志。

alt text


4

在32位Windows上,您可以通过使用/3gb标志启动Windows并将您的应用程序标记为“大地址意识”来获得更多内存。


2
在XP中并不是你获得了更多的内存(即那4GB的RAM的更多),而是你可以运行高达3GB RAM的进程。http://msdn.microsoft.com/en-us/library/ms791558.aspx - Tom Kidd
1
同时也不要在虚拟PC或虚拟服务器中使用它。http://blogs.msdn.com/virtual_pc_guy/archive/2004/12/23/331100.aspx - Tom Kidd
有人知道在2008服务器中如何运作吗?我假设32位版本仍然是一样的。 - MikeJ
@Matthias 这篇 Technet 博客:Pushing the Limits of Windows: Virtual Memory by Mark Russinovich 包含了更多关于这个主题的信息。 - jrh

1

马蒂亚斯,

这并不是直接回答问题的答案,但是有另一种方法来解决这个问题,可以避免缓存解决方案中的一些大问题,这可能会成为一个主要的头痛之源。(很抱歉我没有任何关于此事的推荐阅读资料。)

我们在以前的项目中实现了这个功能,但它也带来了其他的问题。

对于离线访问,您可以在桌面上使用SQL Express创建数据库(或只缓存所需的部分)。然后您只需要切换应用程序指向的数据库即可。您甚至可以使用它存储差异,并重新传输给服务器-虽然这会带来其他问题。如果需要,您可以更改本地副本的权限,使其只读。

您考虑创建的字典听起来非常像SQL索引。如果可以架构到这样的方式,我会依靠SQL来为您完成这项工作。为什么要重新发明轮子呢?如果这样做,您将不得不仔细考虑缓存过期和内存管理-特别是如果这是一个Windows服务。

祝好运,

山姆


0

与任何其他Windows程序一样,您受到地址空间的限制。也就是说,在32位系统上,您可以拥有2GB的地址空间。在x64上,您可以拥有8TB。

如果您没有8TB的物理内存,它将开始分页。


1
如果你没有8TB的硬盘空间可用(我希望有),那么你就会开始收到OutOfMemoryException的错误。太糟糕了。不过,在我们的开发机器上拥有那样大小的硬盘还需要一段时间。 :( - Matthew Scharley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接