在 .NET 应用程序中预分配(保证)内存

Posted

技术标签:

【中文标题】在 .NET 应用程序中预分配(保证)内存【英文标题】:Pre-allocate (guarantee) memory in a .NET application 【发布时间】:2015-03-21 22:31:15 【问题描述】:

.NET 3.5 应用程序是否可以告诉 .NET 运行时:“嘿,我稍后将使用 n MB 内存,所以请提交那么多 现在还是失败现在?”

上下文是:我有一个 C# 控制台应用程序,它运行一个返回大量数据的数据库查询,然后对其进行一些处理。查询可能需要很长时间(数小时),并且随着结果的读取,内存使用量会不断增加。查询完成后,由于我需要做的处理,内存会立即出现峰值。如果机器没有足够的内存,那么应用程序就会失败——在查询上浪费了几个小时!这对用户来说是非常令人沮丧的。如果没有足够的 RAM,我希望应用程序快速失败。

当然,我可以尝试一些技巧,例如分配一个我并不真正需要的大型数组,然后在我真正需要内存之前将其设置为 null,但这并不理想,因为它实际上可能会导致进程当它本来有足够的内存时就会耗尽内存。理想情况下,我不希望使用比需要更多的内存,但除非在我的应用程序运行的整个时间内可以保证一定数量,否则只会在早期失败。这可能吗?

【问题讨论】:

您确定您的处理在内存中的数据上受 CPU 限制吗?对于需要几个小时的事情,似乎还必须发生很多 IO? 这是一个有趣的问题,可以肯定。也许您可以在处理之前将查询结果缓存到辅助存储(磁盘)或本地数据库。然后,如果出现问题,您可以从本地计算机快速检索。只是一个想法。 这里的基本问题是您不知道需要多少内存。因此,任何预先“保留”它的尝试都注定要失败。您需要使查询代码更智能,并且不会无限制地消耗资源。 64 位操作系统在其他方面被高度指出,这在当今并不是一个问题。 我不知道具体需要多少内存,但我可以做出合理的估计。例如,通过运行一个简单的初步查询,我可以估计,在数据库查询完成后,它可能会使用 600-800 MB。在内存处理期间,它可能会达到 1000-1200 MB。这个数量的 RAM 通常应该是可用的,但我无法控制机器上发生的其他事情。当然,我正在尝试减少所需的内存量。这个问题与那个问题是正交的 - 一个可用性改进以避免让用户感到沮丧。 确实知道内存是虚拟的,对吧?您确定您的程序失败是因为没有足够的虚拟内存吗?它不会开始分页而不是失败吗? 【参考方案1】:

您可以尝试使用MemoryFailPoint 类:

try

    using (new System.Runtime.MemoryFailPoint(20)) // 20 megabytes
    
        ...
    

catch (InsufficientMemoryException)

    ...

【讨论】:

不错的发现。在这一点上,我还建议提问者保留查询结果并将任何连接/接口处理到数据库。可以从存储中重新加载结果以确保只有获取的数据在内存中,并且没有其他内部缓存。还应检查处理代码以确保没有泄漏。 这看起来很有用 - 谢谢! MSDN 说“MemoryFailPoint 不保证在门的生命周期内内存的长期可用性”,所以它不是万无一失的,但仍然很有希望。 尝试了一段时间后,我不幸地发现它太不可靠了(对我来说)没有任何实际用途。通常,MemoryFailPoint 构造函数会抛出异常,但处理仍然会成功。其他时候,MemoryFailPoint 不会抛出,但处理之后无论如何都会耗尽内存。

以上是关于在 .NET 应用程序中预分配(保证)内存的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ std::unordered_map 中预分配桶

确定特定 .NET 程序集分配的内存量

为啥在分配大量内存时我的线程化 .Net 应用程序不能线性扩展?

如何查看给定 .NET 应用程序中的内存分配?

如何查看给定 .NET 应用程序中的内存分配?

Glide:在内存缓存中预加载图像(有或没有磁盘缓存)