gpt4 book ai didi

c# - Array.Clear() 与 Buffer.BlockCopy()

转载 作者:太空宇宙 更新时间:2023-11-03 18:56:30 27 4
gpt4 key购买 nike

背景

I have to clear fixed-length managed byte arrays (ex: byte[4096]) very frequently.

我的问题是寻找一个适用于通用用法的答案,但对于那些想知道这个问题出处的人来说:我目前正在优化我的 byte[] 对象池。当它回到游泳池时,我需要把它擦干净。


我的问题

Between using the Array.Clear() method to clear the array or usingBuffer.BlockCopy() method to overwrite the array with a blank one,which method will perform better?


示例代码

使用Buffer.BlockCopy清除字节数组

Buffer.BlockCopy(blankArray, 0, array, 0, 4096);

- 对比 -

使用Array.Clear清除字节数组

Array.Clear(array, 0, 4096);

我的研究

public class Benchmark
{
const int NUMBER_OF_ITERATIONS = 10000000;
const int SIZE = 4096;
static byte[] _blank = new byte[SIZE];
static byte[] _array = new byte[SIZE];

public static int ArrayClear()
{
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++)
{
Array.Clear(_array, 0, SIZE);
}

return NUMBER_OF_ITERATIONS;
}

public static int BlockCopy()
{
for (int i = 0; i < NUMBER_OF_ITERATIONS; i++)
{
Buffer.BlockCopy(_blank, 0, _array, 0, SIZE);
}

return NUMBER_OF_ITERATIONS;
}
}

用于运行基准测试的代码

public class Program
{
static Func<int>[] labs =
{
Benchmark.BlockCopy,
Benchmark.ArrayClear,
};

static void Main(string[] args)
{
for (int i = 0; i < labs.Length; i++)
{
long counter = 0;
int[] gcCounters = new int[]
{
GC.CollectionCount(0),
GC.CollectionCount(1),
GC.CollectionCount(2)
};

Console.WriteLine(labs[i].Method.Name + "()");
Stopwatch stopwatch = Stopwatch.StartNew(); // start benchmark
counter = labs[i].Invoke();
stopwatch.Stop(); // end of benchmark

DisplayResults(gcCounters, stopwatch, counter);
}

Console.Write("\nPress any key to continue...");
Console.ReadKey();
}

static void DisplayResults(int[] gcCounters, Stopwatch stopwatch, long counter)
{
Console.WriteLine(
"Total elapsed time was {0:N2} seconds",
(stopwatch.Elapsed.TotalMilliseconds / 1000)
);
Console.WriteLine(
"Total garbage collection (generation 0) was {0} collections",
(GC.CollectionCount(0) - gcCounters[0]).ToString("N0")
);
Console.WriteLine(
"Total garbage collection (generation 1) was {0:N0} collections",
(GC.CollectionCount(1) - gcCounters[1])
);
Console.WriteLine(
"Total garbage collection (generation 2) was {0:N0} collections",
(GC.CollectionCount(2) - gcCounters[2])
);
if (counter > 0)
{
Console.WriteLine(
"Average processing time per iteration took {0:N2} microseconds",
((double)stopwatch.Elapsed.TotalMilliseconds * 1000 / counter)
);
}
}
}

结果

BlockCopy() 结果

 Total elapsed time was 3.22 seconds.
Total garbage collection (generation 0) was 0 collections.
Total garbage collection (generation 1) was 0 collections.
Total garbage collection (generation 2) was 0 collections.
Average processing time per iteration took 0.32 microseconds.

ArrayClear() 结果

 Total elapsed time was 0.90 seconds.
Total garbage collection (generation 0) was 0 collections.
Total garbage collection (generation 1) was 0 collections.
Total garbage collection (generation 2) was 0 collections.
Average processing time per iteration took 0.09 microseconds.

It seems that ArrayClear is faster. I'm not sure if this means it performs better as well.

最佳答案

您的研究使您得出了正确的结论:Array.Clear() 在此特定场景中优于 Buffer.BlockCopy()

BenchmarkDotNet

要运行这样的基准测试,请使用 BenchmarkDotNet .您的基准测试可以使用 BenchmarkDotNet 进行简化和运行,如下所示:

using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

namespace Experiments
{
[MemoryDiagnoser]
public class Test
{
const int SIZE = 4096;
static byte[] _blank = new byte[SIZE];
static byte[] _array = new byte[SIZE];

[Benchmark]
public void ArrayClear()
{
Array.Clear(_array, 0, SIZE);
}

[Benchmark]
public void BlockCopy()
{
Buffer.BlockCopy(_blank, 0, _array, 0, SIZE);
}
}

public class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<Test>();
}
}
}

结果

我在 x86 和 x64 下的 .NET Framework 以及 x64 下的 .NET Core 上运行了这个基准测试。以下结果表明,在所有实验中,Array.Clear() 优于 Buffer.BlockCopy():

# Clr 4.0.30319.42000, 32bit LegacyJIT-v4.7.2053.0

Method | Mean | StdDev | Allocated |
----------- |------------ |---------- |---------- |
ArrayClear | 154.6503 ns | 0.0192 ns | 0 B |
BlockCopy | 655.8208 ns | 0.0939 ns | 0 B |

# Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2053.0

Method | Mean | StdDev | Allocated |
----------- |------------ |---------- |---------- |
ArrayClear | 179.2065 ns | 0.0205 ns | 0 B |
BlockCopy | 320.4117 ns | 0.0380 ns | 0 B |

# .NET Core 4.6.25211.01, 64bit RyuJIT

Method | Mean | StdDev | Allocated |
----------- |------------ |---------- |---------- |
ArrayClear | 107.5015 ns | 0.0145 ns | 0 B |
BlockCopy | 221.3139 ns | 0.0449 ns | 0 B |

关于c# - Array.Clear() 与 Buffer.BlockCopy(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44055913/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com