在执行操作之前,MemoryFailPoint
(MSDN)" 会检查是否有足够的内存资源。"
但它是如何实际使用的?
MemoryFailPoint
是否为我创建的下一个大对象自动保留了一些内存?或者它只是检查内存是否是免费的,而不保留它?
它是否检查物理内存,物理内存加页面文件,虚拟地址空间或其他内容?
我什么时候处理它?我是否需要在实际创建需要内存的对象之前处置MemoryFailPoint
,或者在处置MemoryFailPoint
之前是否必须创建对象?
e.g。
try
{
using (MemoryFailPoint mem = new MemoryFailPoint(500))
{
// allocate big object here?
}
}
catch (InsufficientMemoryException e)
{
// ...
}
// or allocate big object here?
// or allocate big object on another thread?
同一进程中的另一个线程是否可以使用MemoryFailPoint
窃取我保留的内存,或MemoryFailPoint
是否为当前线程专门保留内存?
如果未处理MemoryFailPoint
会怎样?一个没有问题的MemoryFailPoint
本身会消耗大量的内存吗?
答案 0 :(得分:3)
MemoryFailPoint
的源代码位于.NET Source。课程开头的描述性评论回答了你的问题。我在这里复制该评论以便于参考:
此类允许应用程序在启动之前失败 活动。这个想法是提前失败,而不是在中间失败 一些长期运行的操作,以提高生存能力 应用程序并确保您不必编写棘手的代码来处理 OOM应用程序代码中的任何位置(这意味着状态损坏,意味着你 应该卸载appdomain,如果你有一个交易环境来确保 个别交易的回滚)。这是一个不完整的尝试工具 将所有OOM故障从您的工作方法中的任何位置提升到一个 更容易处理OOM失败的特殊点,你可以 如果它可能会失败,可以选择不启动工作项。这样做 不直接帮助你的代码执行(除了帮助避免 AD卸载)。重点是避免在可能失败的情况下开始工作 企业服务团队已经有效地使用了这些内存门 十年未受管理的世界。
在惠德贝,我们只需检查是否有足够的可用内存 在OS的页面文件&试图确保可能有足够的空间 在进程的地址空间内(检查地址空间碎片) 以及)。我们不会提交或保留任何记忆。避免----用 使用MemoryFailPoints的其他线程,我们也会跟踪一个 通过所有当前活动的“保留”进程范围的内存量 MemoryFailPoints。这有两个问题:
1. This can account for memory twice. If a thread creates a MemoryFailPoint for 100 MB then allocates 99 MB, we'll see 99 MB less free memory and 100 MB less reserved memory. Yet, subtracting off the 100 MB is necessary because the thread may not have started allocating memory yet. Disposing of this class immediately after front-loaded allocations have completed is a great idea. 2. This is still vulnerable to ----s with other threads that don't use MemoryFailPoints.
所以这堂课远非完美。但它可能足够好 有意义地降低托管应用程序中OutOfMemoryExceptions的频率。
在Orcas或更高版本中,我们可能会从操作系统中分配一些内存并添加它 到此线程的分配上下文。显然,在那一点上我们需要 当我们释放这块内存时,有些传达方式。所以,我们 在Whidbey中实现此类型的IDisposable并期望所有用户都可以调用 这来自于一个使用块,为它们的记忆提供词法范围 用法。对Dispose的调用(隐含的使用块)将给我们一个 或许,有机会释放这种记忆。我们预计这将给予 我们可以在未来版本中实现更有效的设计。
在Orcas,我们可能还需要区分可能的分配 进入正常的托管堆与大对象堆,或者我们应该 考虑在两个地方检查足够的可用空间(任何地方) 适当调整以确保内存是连续的。)
答案 1 :(得分:0)
使用模式如下:
const int sizeMB = 500;
using (MemoryFailPoint mem = new MemoryFailPoint(sizeMB))
{
// Allocate sizeMB - large object here. The allocation is *likely* going to succeed.
}
当MemoryFailPoint构造函数失败时,大对象分配很可能抛出OOM。即使成功,它也会使该过程对其他(甚至更小的)内存分配操作更不稳定。
在我的16 GB Windows环境中,下面的示例比没有MemoryFailPoint的OOM更早地(步骤= 5)生成了一次迭代(步骤= 5)的InsufficientMemoryException(在步骤= 6):
List<byte[]> arrays = new List<byte[]>();
const int size = int.MaxValue/2;
const int sizeMB = size / 1024 / 1024;
for(int step = 0; step < 10000; step++)
{
using (new MemoryFailPoint(sizeMB))
{
arrays.Add(new byte[size]);
}
}