【问题标题】:Memory limitations in a 64-bit .Net application?64 位 .Net 应用程序中的内存限制?
【发布时间】:2011-08-31 17:29:10
【问题描述】:

在我的笔记本电脑上,运行 64 位 Windows 7 和 2 Gb 可用内存(由任务管理器报告),我能够做到:

var x = new Dictionary<Guid, decimal>( 30 * 1024 *1024 );

如果我手头没有一台具有更多 RAM 的计算机,我想知道这是否会扩展,以便在具有 4 Gb 可用内存的计算机上,我将能够分配 60M 项而不是“仅”30M 等等开吗?

或者在我能够使用所有可用 RAM 之前,我会遇到其他限制(.Net 和/或 Windows)吗?

更新:好的,所以我不允许分配大于 2 Gb 的单个对象。知道这一点很重要!但是我当然很想知道我是否能够通过像这样分配 2 Gb 块来充分利用所有内存:

  var x = new List<Dictionary<Guid, decimal>>();
  for ( var i = 0 ; i < 10 ; i++ )
    x.Add( new Dictionary<Guid, decimal>( 30 * 1024 *1024 ) );

如果计算机有 >20Gb 的可用内存,这会起作用吗?

【问题讨论】:

    标签: c# .net windows memory-management 64-bit


    【解决方案1】:

    .NET 中的所有对象都有 2 GiB 的限制,您永远不能创建超过 2 GiB 的单个对象。如果您需要更大的对象,则需要确保对象是由小于 2 GiB 的部分构建的,因此您不能拥有大于 2 GiB 的连续位数组或大于 512 MiB 的单个字符串,我不是完全确定字符串,但我已经对这个问题进行了一些测试,当我尝试分配大于 512 MiB 的字符串时,我得到了 OutOfMemoryExceptions。

    尽管这些限制会受到堆碎片的影响,即使 GC 确实尝试压缩堆,大对象(有点随意跨越大约 80K)最终会出现在大对象堆上,该堆是没有压实。严格来说,有点附带说明,如果您可以将短期分配保持在此阈值以下,那么您的整体 GC 内存管理和性能会更好。

    【讨论】:

    • 非常感谢您提供此信息!我更新了我的问题。在我将此答案标记为已接受之前,请随时对此发表评论。 :-)
    • @danbystrom - 正如我所说,这取决于堆碎片。大对象堆可能会变得碎片化,当这种情况发生时,您最终会在内存空间中出现漏洞(这就是碎片化)。如果内存请求不适合任何可用的漏洞并且系统无法释放更多内存,您将遇到 OutOfMemoryException,尽管有足够多的可用系统总内存。这是因为内存总是被分配为连续的字节块(这也不例外)。这里的一般规则是,让您的分配保持短期和小规模。
    • 我真的无法回答 30 MiB 是否是一个好的选择,因为这取决于您的应用程序的内存访问模式。如果您觉得有问题,可以使用一些工具来诊断这些问题,例如内存分析器。如果您还不知道问题出在哪里,他们可以提供必要的洞察力。
    • 好的,我很清楚堆碎片问题。我更想知道病毒机器的限制等是否有任何令人讨厌的惊喜。现在我将继续假设我将能够利用机器上的所有空闲内存——直到被证明是错误的!
    • 在我看来,我不是虚拟机专家,如果做得对,虚拟机和非虚拟机之间的软件应该没有区别。尤其是在 CLR 世界(托管环境)中的抽象级别。
    【解决方案2】:

    更新:随着 .NET 4.5 的发布,2Gb 单对象内存限制已在 64 位上解除。

    您需要在 app.config 中设置 gcAllowVeryLargeObjects

    不过,数组中元素的最大数量仍然是 2^32-1。

    更多详情请见Single objects still limited to 2 GB in size in CLR 4.0?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-05
      • 2011-01-24
      • 2015-11-05
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      • 2017-07-23
      • 2012-01-30
      相关资源
      最近更新 更多