我有一部分代码可以在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
类的代码,因此如果需要,我可以更改它。
答案 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()里面注释掉它的大部分功能。然后运行你的循环并测量记忆。逐渐取消它的一部分,直到你看到一个短暂的。现在你越来越接近导致'泄漏'的原因。