我們之前提到 List 是 .NET 中常用的資料結構,其在儲存大量資料時,如果能夠指定它的初始化容量,就會有效能提升。這個最佳化的方法並不是很明顯,因此本文將使用 BenchmarkDotNet 庫,透過定量對比的方式來證明這一點。
實驗過程
引入 BenchmarkDotNet
首先,我們需要在專案中引入 BenchmarkDotNet 庫。這可以透過在專案的 NuGet 包管理器中搜尋並安裝 BenchmarkDotNet 來實現。
指定需要測試的方法和引數
接下來,我們需要指定需要測試的方法和引數。這可以透過在程式碼中使用 [Benchmark] 屬性來實現。例如,我們可以在測試類中定義兩個測試方法,一個使用指定容量的 List,一個使用未指定容量的 List。
public class ListBenchmark
{
[Benchmark]
public void ListWithCapacity()
{
var list = new List<int>(1000000);
for (int i = 0; i < 1000000; i++)
{
list.Add(i);
}
}
[Benchmark]
public void ListWithoutCapacity()
{
var list = new List<int>();
for (int i = 0; i < 1000000; i++)
{
list.Add(i);
}
}
}
我們還可以使用其他引數來指定測試的一些細節,如使用的 .NET 框架版本,是否進行記憶體測量等。
[SimpleJob(RuntimeMoniker.Net70)]
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
[MemoryDiagnoser]
public class ListBenchmark
{
[Benchmark]
public void ListWithCapacity()
{
var list = new List<int>(1000000);
for (int i = 0; i < 1000000; i++)
{
list.Add(i);
}
}
[Benchmark]
public void ListWithoutCapacity()
{
var list = new List<int>();
for (int i = 0; i < 1000000; i++)
{
list.Add(i);
}
}
}
執行測試
最後,我們可以使用 BenchmarkRunner 類來執行測試。這可以透過在 Main 方法中呼叫 BenchmarkRunner.Run<T>()
方法來實現。其中 T 是包含測試方法的類的型別。
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<ListBenchmark>();
}
}
實驗結果
執行測試後,我們可以得到若干個指標的測試結果。這些指標可能包括執行時間、記憶體使用量等。透過對比這些指標,我們可以得出結論:使用指定容量的 List 效能優於未指定容量的 List。
例如,我們可以看到,使用指定容量的 List 的平均執行時間要比未指定容量的 List 少得多,記憶體使用量也更少。
// * Summary * BenchmarkDotNet=v0.13.2, OS=Windows 11 (10.0.22000.1335/21H2) 12th Gen Intel Core i7-12700, 1 CPU, 20 logical and 12 physical cores .NET SDK=7.0.101 [Host] : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2 .NET 7.0 : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2 .NET Core 3.1 : .NET Core 3.1.32 (CoreCLR 4.700.22.55902, CoreFX 4.700.22.56512), X64 RyuJIT AVX2 | Method | Job | Runtime | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | |-------------------- |-------------- |-------------- |---------:|----------:|----------:|---------:|---------:|---------:|----------:| | ListWithCapacity | .NET 7.0 | .NET 7.0 | 1.392 ms | 0.0302 ms | 0.0891 ms | 164.0625 | 164.0625 | 164.0625 | 3.81 MB | | ListWithoutCapacity | .NET 7.0 | .NET 7.0 | 2.602 ms | 0.0503 ms | 0.0559 ms | 507.8125 | 500.0000 | 500.0000 | 8 MB | | ListWithCapacity | .NET Core 3.1 | .NET Core 3.1 | 1.168 ms | 0.0227 ms | 0.0278 ms | 218.7500 | 218.7500 | 218.7500 | 3.81 MB | | ListWithoutCapacity | .NET Core 3.1 | .NET Core 3.1 | 2.652 ms | 0.0520 ms | 0.0461 ms | 507.8125 | 500.0000 | 500.0000 | 8 MB |
總結
本文透過 BenchmarkDotNet 庫,使用定量對比的方式,證明了使用指定容量的 List 效能優於未指定容量的 List。這是因為指定容量的 List 在初始化時,會為其分配指定大小的記憶體空間,而未指定容量的 List 則會在新增元素時,根據需要動態分配記憶體空間。因此,使用指定容量的 List 可以減少記憶體分配的次數,從而提升效能。
參考資料
- BenchmarkDotNet[1]
本文采用 Chat OpenAI 輔助注水澆築而成,如有雷同,完全有可能。
- 本文作者: newbe36524
- 本文連結: https://www.newbe.pro/ChatAI/How-to-use-benchmark-to-compare-performance-about-list-with-capacity-specified/
- 版權宣告: 本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協議。轉載請註明出處!
參考資料
[1]BenchmarkDotNet: https://benchmarkdotnet.org/