我怎么知道我是否要获得OutOfMemoryException?

时间:2011-08-25 15:53:10

标签: c# .net

我有一个程序可以处理大量数据,并且可以缓存大部分数据,以便在内存中使用后续记录。我缓存的越多,它的工作速度就越快。但如果我缓存太多,繁荣,重新开始,这需要更长的时间!

在异常发生后尝试做任何事情都没有太成功 - 我无法获得足够的内存来做任何事情。

此外,我尝试分配一个巨大的对象,然后立即取消分配,结果不一致。也许我做错了什么?

无论如何,我所坚持的只是在缓存对象的#上设置一个硬编码限制,从经验来看,它似乎足够低。还有更好的想法?感谢。

回答后编辑

以下代码似乎完全符合我的要求:

Loop 
    Dim memFailPoint As MemoryFailPoint = Nothing
    Try
        memFailPoint = New MemoryFailPoint( mysize) ''// size of MB of several objects I'm about to add to cache 
        memFailPoint.Dispose()
    Catch ex As InsufficientMemoryException
        ''// dump the oldest items here
    End Try
   ''// do work
next loop.

我需要测试它是否在这种安排中减慢了速度,但我可以看到任务管理器中的黄线看起来像一个非常健康的锯齿模式,并且具有一致的顶部!#/ p>

6 个答案:

答案 0 :(得分:8)

您可以在分配前使用MemoryFailPoint检查可用内存。

答案 1 :(得分:1)

您可能需要考虑缓存对象的发布策略。没有可能的方法可以永久保存所有这些,因此您需要提出过期时间表并从内存中删除较旧的缓存对象。应该可以找出剩余多少内存并将其用作策略的一部分但有一点是肯定的,旧对象必须去。

答案 2 :(得分:1)

您可以使用许多指标来跟踪您的流程使用的内存量:

问题在于,没有一种可靠的方法可以单独告诉这些值是否给定的内存分配是否会失败,因为尽管地址空间中可能有足够的空间用于给定的内存分配内存碎片意味着空间可能不连续,因此分配可能仍然失败。

但是,您可以使用这些值来指示进程正在使用多少内存,因此您是否应该考虑从缓存中删除对象。

更新:确保您了解虚拟内存和物理内存之间的区别非常重要 - 除非您的页面文件已被禁用(非常不可能)OutOfMemoryException将导致是由于虚拟地址空间不足/碎片造成的。

答案 3 :(得分:1)

如果使用WeakRerefence(http://msdn.microsoft.com/en-us/library/system.weakreference.aspx)实现缓存,将使缓存的对象仍然符合垃圾回收的条件否则您可能抛出OutOfMemory异常的情况。

这是固定大小缓存的替代方案,但在GC确实发生时清除缓存可能会过于激进。

您可能会考虑采用混合方法,其中cahce中存在(可调整的)固定数量的非弱引用,但您还会通过弱引用来增加它。或者这可能有点矫枉过正。

答案 4 :(得分:0)

如果您只使用托管资源,则可以使用GC.GetTotalMemory方法,并将结果与​​架构上进程的最大允许内存进行比较。

更高级的解决方案(我认为这是SQL Server实际适应可用内存的方式)是使用CLR Hosting APIs

  

接口允许CLR通知主机的后果   没有特定的分配

这意味着实际上从缓存中删除了一些对象并再次尝试。

无论如何,我认为除非你真的需要一个惊人的表现,否则对于几乎所有应用来说这可能是一种过度杀伤力。

答案 5 :(得分:0)

简单的答案......知道你的记忆限制是什么。

越接近该限制,您就越有可能获得OutOfMemoryException。

更详细的答案....除非你自己编写了一种机制来做这种事情,否则编程语言/系统不会那样工作;据我所知,他们无法提前告知您或提前告知您超出限制但是,他们很乐意在问题发生时通知您,并且通常会通过您应该编写代码来处理的异常情况发生。

内存是您可以使用的资源;它有限制,它还有一些约定和规则供您遵循以充分利用该资源。

我相信你正在做的设置一个好的限制,硬编码或可配置,似乎是你最好的选择。