繁体   English   中英

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

[英]How do I know if I'm about to get an OutOfMemoryException?

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

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

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

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

回答后编辑

以下代码似乎正在做我想要的:

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.

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

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

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

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

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

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

更新:确保您了解虚拟内存和物理内存之间的区别也很重要 - 除非您的页面文件被禁用(非常不可能), OutOfMemoryException原因将由虚拟地址空间的缺失/碎片引起。

如果您使用WeakRerefence (http://msdn.microsoft.com/en-us/library/system.weakreference.aspx)实现缓存,这将使缓存的对象仍然有资格进行垃圾收集,否则您可能会抛出OutOfMemory异常。

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

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

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

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

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

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

无论如何,我认为除非你真的需要一个惊人的性能,否则几乎所有的应用程

简单的答案......通过了解你的记忆限制。

越接近该限制,您就越需要获得OutOfMemoryException。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM