这个流行的StackOverflow答案是否不正确?

时间:2011-08-16 20:07:20

标签: c# performance optimization

我所指的帖子是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。

三个测试,每个测试都得出结论,将前限存储作为性能提升的最佳解决方案。我错过了什么吗?目前我的程序优化是必需的,因为大图片被处理,并且在所有性能关键区域我总是存储环路的边界以获得性能增益,这些测试似乎证实了这一点。

2 个答案:

答案 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   ]