[英]Array.Clear() vs Buffer.BlockCopy()
我必須非常頻繁地清除固定長度的字節數組(例如:
byte[4096]
)。
我的問題是尋求適用於通用用法的答案,但對於那些想知道該問題源自何處的人:我目前正在優化我的byte[]
對象池。 當它回到游泳池時,我需要擦干凈。
在使用
Array.Clear()
方法清除數組還是使用Buffer.BlockCopy()
方法覆蓋空白數組之間,哪種方法效果更好?
使用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.
似乎
ArrayClear
更快。 我不確定這是否意味着它也會表現更好。
您的研究已經得出正確的結論:在這種特定情況下, Array.Clear()
性能優於Buffer.BlockCopy()
。
要運行這樣的基准,請使用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 |
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.