2014-03-12 96 views
7

在复杂的图像处理算法的最后,我们有以下代码将结果保存到文本文件。该函数的输入是一个float[,] p_RangeMap表示图像处理的输出:.net性能周期?

StringBuilder stringBuilder = new StringBuilder(30 * 1024 * 1024); 
stringBuilder.AppendLine("Row" + ms_csvSeparator + p_RangeMap.GetLength(0)); 
stringBuilder.AppendLine("Col" + ms_csvSeparator + p_RangeMap.GetLength(1)); 

Stopwatch stopwatch = Stopwatch.StartNew(); 

for (int y = 0; y < p_RangeMap.GetLength(0); y++) 
{ 
    for (int x = 0; x < p_RangeMap.GetLength(1); x++) 
    { 
      stringBuilder.Append(p_RangeMap[y, x].ToString(CultureInfo.InvariantCulture)); 
      stringBuilder.Append(ms_csvSeparator); 
    } 
    stringBuilder.AppendLine(); 
} 

stopwatch.Stop(); 
Console.WriteLine("MeasureRunTime: RangemapConvert: " + stopwatch.Elapsed); 

通过测量这些线6000次的迭代的运行时,我们得到了如下图:

Code running time

6000迭代大约需要24小时才能运行。水平轴表示迭代,垂直轴表示这些线以秒计算的运行时间。输入对于每次迭代完全相同,并且p_RangeMap的尺寸是1312 x 3500.

它从大约两秒开始,并且在上升到13秒之后,在900次迭代之后回落,并且(大约)900个周期形成一个周期。正如你所看到的最高值约为22秒。

任何想法可能导致这种运行时变化?

什么可能导致周期性?

可能值得一提的是,代码的其他部分显示了相同的行为,但是这部分是从源代码中最容易获取的。

UPDATE1

我已经更新了代码示例中,StringBuilder的是预分配与文件大小的一个粗略的估计。我们也考虑过垃圾回收,请考虑以下事项:

900个周期意味着大约3.5小时,大约16 GB的处理后的输入数据(从文件一次又一次地加载相同的图片)。更不用说因为各种原因在图像处理过程中创建的副本。我认为GC应该更频繁地触发。

16 GB来源于:1312 * 3500 * 4 * 900

+10

考虑到操作涉及分配,我希望垃圾收集... –

+1

考虑预先分配的StringBuilder - 我认为结果是相当大的,如果它有它的效率不高经常扩大规模。如果结果进入一个文件,请考虑在一个较小的stringbuilder中逐行输出它 - 这看起来像gc问题,这是一个可能的原因。 – TomTom

+0

我已经更新了这个问题,StringBuilder是预先分配的。逐行输出这些线条听起来很有意思,我们可以尝试。将更新与结果的职位。 – toderik

回答

1

首先看看:

我的猜测是内存问题。图中的急剧下降看起来像是垃圾收集中的GC踢。

Stringbuilder相当高效,但我怀疑它是否在构建时考虑到这种情况。

5

这非常有趣。根据你的更新,你在哪里分配16GB,你可能会考虑将你的Float数组和字符串生成器封装在一个允许你重用缓冲区的类中,而不是在每次重新运行时重新分配它们。 (比如每次调用整个函数时重用相同的字符串构建器和数组,因此每6,000次运行只创建一个实例)

原因如下:您的构建器大小约为30MB,因此它被分配到大对象堆中。 (任何时候分配超过85,000字节,它进入LOH)。关于LOH的GC规则有点不同。首先,它只是在第二代集合(最昂贵的类型)上GC'd,因此如果您大量创建并拆除大量分配,则可能会迫使Gen2集合更频繁地发生。此外,LOH在第二代GC上没有进行碎片整理(因为它太昂贵了),所以当您分配大量数据时,您更可能导致GC,因为您需要线性32MB。

如果你包装你的浮点数组和字符串生成器,在你的字符串生成器之间调用Clear()来清空它而不释放它,并且跟踪float数组的已用大小。

这里的一对LOH的文章:http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

+1

感谢您的链接,我们将尽力尝试您的建议,并会通知您有关结果。 – toderik

+1

酷!期待它! – JMarsch

+1

您可以选择压缩.NET 4.5.1上的LOH - http://msdn.microsoft.com/en-us/library/system.runtime.gclargeobjectheapcompactionmode(v=vs.110).aspx –