使用double数组时内存泄漏

时间:2010-05-06 19:57:50

标签: c# memory-management

我有一部分代码可以在double的大型数组上运行(至少包含大约6000个元素)并执行数百次(通常为800次)。

当我使用标准循环时,就像那样:

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
singleRow = someObject.producesOutput();
//...
// do something with singleRow
// ...
}

内存使用量增加约40MB(从循环开始时的40MB到最后的80MB)。

当我强制在每次迭代时使用垃圾收集器执行时,内存使用量保持在40MB的水平(上升是无关紧要的)。

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
singleRow = someObject.producesOutput();
//...
// do something with singleRow
// ...
GC.Collect()
}

但是执行时间要长3倍! (这很关键)

如何强制C#使用相同的内存区域而不是分配新内存? 注意:我可以访问someObject类的代码,因此如果需要,我可以更改它。

3 个答案:

答案 0 :(得分:7)

为什么要分配一个大的空singleRow来覆盖它?也许你应该传入数组来修改它的值。这将允许您重复使用它。

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
    someObject.FillWithOutput(singleRow);
    //...
    // do something with singleRow
    // ...
}

如果该方法有时填充少于6000个元素,则可以简单地返回填充计数。或者,您可以使用List<double>,这将允许调整大小。

答案 1 :(得分:3)

singleRow作为参数并将其传递给每次调用producesOutput ...

基本上你的producesOutput方法可能每次都会分配一个新的数组,重新分配singleRow只是将旧内存标记为 available 来删除,但不是出于性能原因运行GC。

答案 2 :(得分:0)

你不会喜欢这个,但是如果你必须强迫GC你做错了什么。请记住,内存可能会增长,直到触发GC的压力 - 这是一件好事,因为这意味着GC必须运行才能运行。

这是一个愚蠢的测试,但它可能会对正在发生的事情有所了解。在FillWithOutput()里面注释掉它的大部分功能。然后运行你的循环并测量记忆。逐渐取消它的一部分,直到你看到一个短暂的。现在你越来越接近导致'泄漏'的原因。