c# – .Net性能周期?

我们在复杂图像处理算法的最后有以下代码,用于将结果保存到文本文件中.函数的输入是float [,] p_RangeMap,它表示图像处理的输出:
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次,我们得到了以下图表:

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

解决方法

这很有趣.根据您的更新,在分配16GB的情况下,您可以考虑将Float数组和字符串构建器包装在允许重复使用缓冲区的类中,而不是在每次重新运行时重新分配它们. (比如每次调用整个函数时重用相同的字符串构建器和数组,因此每6,000次运行只创建一个实例)

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

如果你把你的float数组和你的字符串构建器包起来,在你的字符串生成器之间调用Clear(),在不释放它的情况下清空它,并跟踪使用的大小,我会非常好奇你的perf是什么样的.你的浮点数组.

这是一篇关于LOH的文章:http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

相关文章

1 在Visual Studio 中创建一个Asp.NET WebApi 项目,项目名:...
using ImpromptuInterface; using System; using System.Dyn...
https://blog.csdn.net/michaelgong/article/details/431485...
C#11添加了文件作用域类型功能:一个新的file修饰符,可以应...
在.NET中Newtonsoft.Json(Json.NET)是我们常用来进行Json序列...
设置允许跨域访问的网址--&gt; 设置预检有效时间--&...