在重构一些旧代码时,我决定进行一些毫无意义的过早优化,并重新使用缓冲区,而不是每次都重新分配它。 令我惊讶的是,我发现它的运行速度非常慢。
复制:
private static void Main(string[] args)
{
const int N = (int)1e4;
const int size = 100 * 1024;
var sw = Stopwatch.StartNew();
var buffer = new byte[size];
for (int n = 0; n < N; n++)
{
buffer = new byte[size];
}
var reallocMs = sw.ElapsedMilliseconds;
sw = Stopwatch.StartNew();
buffer = new byte[size];
for (int n = 0; n < N; n++)
{
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = 0;
}
}
var rewriteMs = sw.ElapsedMilliseconds;
Console.WriteLine($"Reallocating: {reallocMs} ms");
Console.WriteLine($"Rewriting: {rewriteMs} ms");
Console.WriteLine($"Rewrite / reallocate = {(double)rewriteMs / (double)reallocMs}");
}
当内置于Release
中时,重写每个字节比重新分配新缓冲区慢大约8倍。在Debug
中,它的速度降低了近50倍!
这怎么可能?我希望使用固定的缓冲区可以提高性能,但是事实并非如此。
我在这里想念什么?
PS:而且,Array.Clear()
始终比for循环还要慢 ,尽管其性能与构建配置无关。>
答案 0 :(得分:2)
每次写入数组时,它都可能引发异常。因此,在循环实现中的每次写入时,都会对索引进行边界检查。首次初始化已知内存范围时,可以对其进行优化。