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

21

一个.NET 3.5应用程序是否有可能告诉.NET运行时:“嘿,我后面将要使用 MB内存,请立即分配这么多内存或者立即失败?”

背景是:我有一个C#控制台应用程序,运行一个返回大量数据的数据库查询,然后对其进行一些处理。查询可能需要很长时间(数小时),随着结果被读取,内存使用量不断增加。查询结束后,由于需要进行处理,内存会立即飙升。如果机器没有足够的RAM,则应用程序在该点失败 - 在查询上浪费了几个小时!这对用户来说非常令人沮丧。如果RAM不足,我想让应用程序快速失败。

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


2
这是一个有趣的问题,毫无疑问。也许您可以在处理之前将查询结果缓存到辅助存储器(磁盘)或本地数据库中。然后,如果出现问题,您可以快速从本地机器检索。只是一个想法。 - STLDev
2
这里的基本问题是你不知道需要多少内存。因此,任何试图提前“保留”它的尝试都注定会失败。你需要让查询代码更加智能化,不要无限制地消耗资源。64位操作系统在其他方面非常适用,这些天不算什么问题。 - Hans Passant
1
我不确定需要多少内存,但我可以做出合理的估计。通过运行一个简单的初步查询,我可以估计,例如,在DB查询完成后可能会使用600-800 MB。在内存处理期间,它可能会增加到1000-1200 MB。这个内存量通常应该是可用的,但我无法控制机器上发生的其他事情。当然,我正在尝试减少所需的内存量。这个问题与此无关 - 这是一项可用性改进,旨在避免让用户感到沮丧。 - EM0
2
你知道内存是虚拟的,对吧?你确定你的程序失败是因为没有足够的虚拟内存吗?它不会开始分页而不是失败吗? - John Saunders
@EM 这几乎从来不是问题 - 如果你是唯一的前台应用程序,那么几乎可以保证是 获得了甜蜜的 RAM。Windows(特别是 XP 之后)往往非常快地清除后台应用程序使用的 RAM(我不确定,但我记得大多数情况下内存已经在交换文件中镜像)。 - Luaan
显示剩余6条评论
1个回答

21

你可以尝试使用 MemoryFailPoint 类:

try
{
    using (new System.Runtime.MemoryFailPoint(20)) // 20 megabytes
    {
        ...
    }
}
catch (InsufficientMemoryException)
{
    ...
}

1
很好的发现。在这一点上,我也建议提问者持久化查询结果并丢弃任何与数据库的连接/接口。结果可以重新从存储中重新加载,以确保仅有获取的数据在内存中,没有其他内部缓存。同时,应检查处理代码以确保没有泄漏。 - ceztko
这看起来很有用 - 谢谢!MSDN上说:“在门的生命周期内,MemoryFailPoint对内存的长期可用性不作任何保证”,所以它并非百分之百可靠,但仍然很有前景。 - EM0
经过一段时间的尝试,不幸的是我发现它太不可靠了,对于我来说没有任何实际用途。通常情况下,MemoryFailPoint构造函数会抛出异常,但处理仍然会成功。其他时候,MemoryFailPoint不会抛出异常,但处理后仍会耗尽内存。 - EM0

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