如何使.NET进程耗尽内存而不会耗尽所有系统内存

时间:2009-05-07 18:15:06

标签: .net unit-testing nunit out-of-memory

问题很简单我有一个进程,它在某些xml文件上执行ETL。我们开始获得非常大的xml文件,并开始获得OutOfMemoryExceptions。

修复过程相对简单。但是,我想为我的NUnit套件进行单元测试,以确保该过程将继续能够处理真正大的文件。但是,实际上我的开发工作站上的内存不足会降低我的机器速度,而且非常耗时。在版本控制中存储一个巨大的测试文件也是一个坏主意。如果我可以人为地限制一个进程,线程或appdomain只使用固定数量的ram,那么就说128 megs,我可以做一个不会让我的工作站瘫痪的小单元测试。

有什么建议吗?他们的一些非托管API是否可以P / Invoke?

4 个答案:

答案 0 :(得分:2)

你不能使用模拟框架进行内存分配,并将OutOfMemoryException作为其中一个测试吗?

尽管如此,如果你真的内存不足,那么你的应用程序可以安全地做不了多少,但如果你至少可以优雅地失败,那么你的用户将会感激不尽。

示例: 我之前的工作中有一个案例,我们实时显示工厂的3D模型。模型变得如此之大,以至于当我们尝试加载纹理时,我们会失去内存故障。我们设法通过确保代码处理空指针来保持应用程序活跃和渲染,即使代码的其余部分认为应该存在纹理信息。

答案 1 :(得分:1)

嘲弄是最好的。实际上提出OOM是通过定义而不是单元测试。在处理内存时,您正在处理负载测试。如果你阅读了这封电子邮件底部的链接,你会发现在最好的情况下,真正的OOM很难再现和调试。设计的OOM异常不是异常的真正原因,因此没有比模拟测试更有趣。

使用模拟进行单元测试以进行验证。如果您仍然获得OOM,请在服务器上投入更多内存,并使您的进程更频繁地回收/重新启动。

这是我上次与他们一起战斗时收集的OutMemoryExceptions的一些有趣读物。摘要:当系统无法分配您请求的数量时,会发生OOM - 这并不意味着您的内存不足。

答案 2 :(得分:0)

我不太明白你在这里得到了什么。让我们假设你以某种方式创建了一个人为小的“测试环境”,它无法分配大块的内存,因此它会在较小的文件上抛出OutOfMemoryExceptions。你有什么收获?单元测试应该测试你是否可以在真实系统上处理更大的文件,对吗?

重要的是,你可以在他们将要运行的任何系统上处理“尽可能大”的文件,并且没有真正的方法进行单元测试,除了尝试该文件之外那个系统。

(一个更小,更不重要的事情可能是你是否优雅地处理OutOfMemoryException,但你不需要实际耗尽内存来测试它;只是让你的方法偶尔抛出一个异常并观察它做对了。)

答案 3 :(得分:0)

很容易在进程中导致内存不足异常。

只需创建一个循环,在块中分配内存,这些块足够小,不会出现在大对象堆上(但不会导致异常),然后你可以尝试打开一个较小的文件,导致文件打开无法分配足够的连续内存,并且在打开文件时无需大量文件就会出现OOM异常。像这样......

List<byte[]> items = new List<byte[]>();
for (int i = 0; i < 10000; i++)
{
     byte[] c = new byte[160000];
     items.Add(c);
}

byte[] next = new byte[1000000000];

如果你按原样运行上面的代码,你将在最后一行得到一个OOM异常。但是,如果你首先注释掉循环它将执行没有错误。您可能需要稍微调整一下循环以使其每次都打开文件失败,但您可以这样做。只需在调用之前运行循环就可以在测试中打开文件,你就会耗尽大量的内存,而你的打开应该会失败。

此外,您可能需要查看设置/ 3GB开关(如果它是您的选项)。它并不总是正确的答案,它有与之相关的缺点,但它将2GB / 2GB的虚拟内存分割形式更改为1GB / 3GB,允许您的进程访问更多的虚拟地址空间。这将为您提供一个可以打开的文件大小更多的喘息空间。同样,你应该在阅读这个问题之前阅读这个问题的缺点,然后再将其作为一个解决方案,并确保它有助于你的情况。

Here是如何在服务器上启用它