我所指的帖子是this.当我将大小增加到100000000时,不仅第一个对我来说运行得更快(563 MS与630相比),而且过去使用for循环中的属性也是如此引起了相当大的速度减速。
一旦写入波形查看器,每帧平均需要23毫秒才能处理。循环遍及整个图片像素的for循环是导致速度减慢的原因。而不是在for循环之前存储图片的宽度和高度,而是在每次迭代期间访问它。在更改它时,处理单个帧的时间从23毫秒变为仅为3。
另外,我制作了这个示例类:
class LOL
{
private int x;
public LOL(int x)
{
this.x = x;
}
public int X
{
get
{
return x;
}
}
}
然后我做了一个迭代5亿次的for循环。一个测试在循环开始之前将X存储在整数变量中,并且在每次迭代期间访问X属性。前者花了大约1,500毫秒,后者花了大约8,000。
三个测试,每个测试都得出结论,将前限存储作为性能提升的最佳解决方案。我错过了什么吗?目前我的程序优化是必需的,因为大图片被处理,并且在所有性能关键区域我总是存储环路的边界以获得性能增益,这些测试似乎证实了这一点。
答案 0 :(得分:5)
不,它看起来对我来说;如果我这样做:
int[] values = new int[100000000];
var watch = Stopwatch.StartNew();
int length = values.Length;
for (int i = 0; i < length; i++)
values[i] = i;
watch.Stop();
var hoisted = watch.ElapsedMilliseconds;
watch = Stopwatch.StartNew();
for (int i = 0; i < values.Length; i++)
values[i] = i;
watch.Stop();
var direct = watch.ElapsedMilliseconds;
并使用优化构建,从控制台运行;我得到direct
为71而hoisted
为163,这与我对JIT的期望有关,消除了对向量的越界检查(但仅在直接访问时)。
答案 1 :(得分:1)
在发布模式下编译,缓存长度更快。在调试时,情况正好相反。
测试方法
public static class Performance
{
public static void Test(string name, decimal times, bool precompile, Action fn)
{
if (precompile)
{
fn();
}
GC.Collect();
Thread.Sleep(2000);
var sw = new Stopwatch();
sw.Start();
for (decimal i = 0; i < times; ++i)
{
fn();
}
sw.Stop();
Console.WriteLine("[{0,15}: {1,-15}]", name, new DateTime(sw.Elapsed.Ticks).ToString("HH:mm:ss.fff"));
Debug.WriteLine("[{0,15}: {1,-15}]", name, new DateTime(sw.Elapsed.Ticks).ToString("HH:mm:ss.fff"));
}
}
测试代码:
var testAmount = 100;
int[] a1 = new int[10000000];
int[] a2 = new int[10000000];
Performance.Test
(
"Direct", testAmount, true,
() =>
{
for (int i = 0; i < a1.Length; ++i)
{
a1[i] = i;
}
}
);
Performance.Test
(
"Cache", testAmount, true,
() =>
{
var l = a2.Length;
for (int i = 0; i < l; ++i)
{
a2[i] = i;
}
}
);
调试结果
[ Direct: 00:00:06.474 ]
[ Cache: 00:00:06.907 ]
发布结果
[ Direct: 00:00:05.382 ]
[ Cache: 00:00:04.714 ]