【问题标题】:How do I create a (32-bit) .NET application to use 3 GB RAM?如何创建(32 位).NET 应用程序以使用 3 GB RAM?
【发布时间】:2010-10-02 15:25:44
【问题描述】:

我正在创建一个需要使用大量 RAM 的 .NET 应用程序 (C#)。我最近知道在 32 位版本的 Windows XP 上我只能使用 2 GB,除非我使用/3Gb 开关,并在可执行文件头中设置IMAGE_FILE_LARGE_ADDRESS_AWARE 标志。但是由于我正在开发一个 .NET 应用程序,我想我不能直接修改可执行文件,可以吗?那么,我应该怎么做才能让我的应用程序使用 3 GB?

【问题讨论】:

  • 如果您需要更高的速度和内存效率,也许您可​​以将矩阵运算和数字运算转移到本机 C++ dll 中?
  • 我打算最终做到这一点,但这需要时间。在那之前,我必须使用现有的 C# 代码库。

标签: .net windows memory


【解决方案1】:

/3GB 开关位于操作系统引导加载程序上,而不是您的应用程序上。 (编辑:它也存在于本机 C/C++ 编译器中,但不存在于 C# 编译器中)就您的应用程序而言,它会请求内存,而操作系统会将其提供给您的进程。但是,在您的程序使用虚拟内存之前,您可以再访问 1 个 gig(根据您的硬件外围设备,您可能并不总是获得 3gig)。

正如 Marc Gavell 向我指出的那样,您可能需要在您的 exe 上运行命令“editbin /LARGEADDRESSAWARE my.exe”作为构建后选项来启用此功能。在这里找到了一位 MS 人员的参考资料:MS Forums

我可以建议你看看你的程序,看看你是否可以重新架构它以使用更少的内存。也许您可以处理较小块的数据集,而不是尝试将整个数据一次加载到内存中?

【讨论】:

  • 谢谢。该应用程序专门构建为尽可能快地消耗所需的内存(用于数字运算和矩阵运算)。但是我是否从您的回答中得知 CLR 设置了 IMAGE_FILE_LARGE_ADDRESS_AWARE 位?
  • @Hosam - 您可以随时在您的 exe 上使用 dumpbin /HEADERS 来找出答案;我刚刚检查过,默认情况下它这样做(至少我的测试)
  • @Spence - 不,您还需要设置 exe 级别的标头标志。
  • 没有编译器标志:msdn.microsoft.com/en-us/library/6ds95cz0(VS.80).aspx 在混合模式的 exe 中,你肯定需要它,但你确定是 c# exe 吗?
  • @Spence - 好吧,我的 理解 是它更多地应用于过程(通过操作系统)而不是实现。我可能是错的......我想我们可以通过强制重内存负载等来测试......
【解决方案2】:

.NET exe 仍然是标准的 PE 文件;因此您可以尝试使用 editbin /LARGEADDRESSAWARE 设置标志,但请注意,如果您使用 ClickOnce 之类的东西(因为它维护文件的加密哈希),这将不起作用。

但是,请注意,就单个对象/数组的最大大小而言,您仍将具有相同的 .NET 限制。对于大量内存,x64 是一个更好的主意。

【讨论】:

  • 谢谢。我不知道这是一个标准的PE!所以它只是加载 JIT 来编译存储在可执行文件中的实际字节码?我理解正确吗?
  • (好吧,严格来说,它只是要求 CLI 接管,而 执行 JIT,但足够接近 ;-p)
  • ++ x64 的道具。这绝对是解决整个 3gb 问题的好方法,而且您不必重新编译,因为 .net 非常棒。
  • 谢谢马克。 :) 我不能使用 64 位,因为我们没有 64 位许可证(适用于 Windows 和第 3 方应用程序)。希望我们能尽快解决这个问题。
  • 这适用于我在 Windows 7(64 位)上使用为 x86 编译的 .EXE;我可以使用我的 exe 分配的总内存从 1.77 GB 变为 3.68 GB。
【解决方案3】:

据我所知,/3GB 开关只能用于 Windows Server(2000 或 2003),而不能用于 Windows XP。您需要在 boot.ini 文件的末尾写入 /3GB。这样,对于应用程序,操作系统可以启用更多通常分配给内核进程使用的内存。但是,/3GB 并不意味着您可以为您的应用程序使用 3GB 的内存,它只是可以使用更多的内存,但不一定必须是 3GB。对于 .net 应用程序,据我所知,使用 /3GB 开关最多可以使用 1.8GB 内存。顺便说一句,您可能还想检查 /PAE 开关。

【讨论】:

  • 谢谢。根据 MSDN (msdn.microsoft.com/en-us/library/bb613473.aspx),Windows XP Professional 支持该开关。至于 .NET 的限制,为什么会限制在 1.8?那太少了! (顺便说一句,我不是在谈论一个连续的数组。)
  • 我的知识主要取决于我 3-4 年前使用 .net 1.1 的经验。我不完全知道其中的主要原因,即使我知道我现在不记得了。但是,每当我遇到 OOM 异常时,转储文件显示使用的总内存为 1.8GB,在 /3GB 切换之前为 800MB。
  • @haken - 这听起来可能与 LOH 的碎片有关,或者与尝试分配单个大型数组(等)有关。只是想法。
  • 我想,可能是我检查的是提交的字节而不是保留的字节,但它仍然不能解释巨大的差异。我们没有那么大的 LO 或类似的东西。但最好不要猜测我不记得确切的东西。
【解决方案4】:

嗯,我不确定,但这是我的想法:

可以通过两种方式编译 .NET 可执行文件 - 特定于平台和独立于平台。默认情况下,它们与平台无关,并且在运行程序时,代码(如其他答案中所述)JIT 到特定于平台的代码。

现在,例如,如果您的可执行文件是这些独立于平台的可执行文件之一,并且您在 64 位操作系统上运行它,那么它将被 JIT 化为 64 位代码,对吗?因此,它将能够处理超过 3GB 的 RAM。

我想说的是 - 我认为 PE 标头中写的内容根本不重要。可用 RAM 的实际数量由 .NET 运行时决定,它反过来会查看当前平台并尽可能生成最佳的 JIT 代码。

我认为您不必担心 /3GB 开关,因为 .NET 会为您处理好它。相信.NET! :)

【讨论】:

  • 如果我在 64 位操作系统上运行它,我目前无法这样做。在 32 位操作系统上,我需要设置大地址感知标志。
  • 对于经典的可执行文件,是的。但是 .NET 可执行文件不是由 Windows 直接执行的!它们首先由 .NET 运行时进行转换,结果产生了完全不同的东西!运行的不是您的 .exe,而是 .NET 生成的。
  • 因此,如果必须在任何地方设置标志,则必须在 .NET 生成的 .exe 上设置,而不是在您的 .exe 上设置!
  • 正如 Marc Gravell 指出的那样,您的 .net exe 实际上是带有 PE 标头的真正 exe。此代码加载,调用加载 CLR 的 Cor_BindToRuntimeEx()。然后 Clr 跳转到 EXE 中 .net 代码的第一个点并开始执行。 Therfore windows 像 C++ exe 一样运行你的 exe :(.
【解决方案5】:

您可以尝试通过命名管道使用远程处理,并通过物理上拥有更多进程来获得更多内存。

如果您正在执行任何形式的互操作(此处计算正常的 .Net 套接字),您应该创建一个对象缓存(例如,使用套接字一个 byte[] 缓冲区)在应用程序启动时分配大量这些对象。

您应该阅读this article

【讨论】:

  • 谢谢,但是远程处理会给我的应用程序带来非常大的开销。
  • 您可能会感到惊讶。使用命名管道(它们是 IPC 通道)可以获得相当好的性能。 +记下修改。
【解决方案6】:

您还应该增加进程的最大工作集大小:请参阅SetProcessWorkingSetSize API。

【讨论】:

  • 谢谢。这是我第一次知道这个功能。一定要叫吗?还是只是以防万一,以免其他应用程序占用我的记忆? (如果机器专用于我的应用程序,我需要它吗?)
  • 如果你不调用它,当你超过你的最大工作集时,操作系统将开始“修剪”你的工作集,将你的内存分页到页面文件(其中,交换与磁盘之间的内存,会影响您的程序和操作系统的性能)。所以你应该调用它,如果你想......
  • ...实际上是在使用所有的内存。或者,如果您对使用 3GB 的 虚拟 内存(不是真实内存,实际 RAM)感到满意,则无需调用它。
  • 那我当然想调用它。 :) 非常感谢!
【解决方案7】:

我刚刚在 Windows 10(64 位)上使用 VS2019 上的一个小型 x86 C# 程序对其进行了测试。 默认情况下,我可以在内存不足之前分配 1605 个 1Mb 大小的字符串。

通过设置:

"editbin /LARGEADDRESSAWARE my.exe"

我可以在内存不足之前分配 3330 个 1Mb 大小的字符串。

在 Windows 10(64 位)上,它因此超过 3Gb 空间寻址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-15
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2011-04-16
    相关资源
    最近更新 更多