使用BenchmarkDotNet测试.NET列表初始化性能时遇内存不足异常
解决.NET List初始化基准测试的OutOfMemoryException问题
问题原因
你的代码抛出System.OutOfMemoryException是因为**[GlobalSetup]只执行一次**,而BenchmarkDotNet会多次重复调用基准测试方法。每次调用都会往同一个List实例中添加BatchSize个元素,随着迭代次数增加,List持续扩容,最终超出内存限制。
解决方案
有两种可行的修复方式:
方式1:使用[IterationSetup]重置List
将全局初始化改为每次迭代前初始化,确保每次基准测试都使用全新的List实例:
using BenchmarkDotNet.Attributes; namespace list_benchmark { public class ListInitializationBenchmark { private List<int> notInitializedList; private List<int> initializedList; [Params(1000, 10000, 100000)] public int BatchSize { get; set; } // 每次基准迭代前执行,重新初始化List [IterationSetup] public void IterationSetup() { notInitializedList = new List<int>(); initializedList = new List<int>(BatchSize); } [Benchmark] public void ProcessNotInitializedList() { for (int i = 0; i < BatchSize; i++) { notInitializedList.Add(i); } } [Benchmark] public void ProcessInitializedList() { for (int i = 0; i < BatchSize; i++) { initializedList.Add(i); } } } }
方式2:在基准方法内部创建List
直接在每个基准测试方法中创建新的List,避免复用实例导致的内存累积,同时返回List防止编译器优化:
using BenchmarkDotNet.Attributes; namespace list_benchmark { public class ListInitializationBenchmark { [Params(1000, 10000, 100000)] public int BatchSize { get; set; } [Benchmark] public List<int> ProcessNotInitializedList() { var list = new List<int>(); for (int i = 0; i < BatchSize; i++) { list.Add(i); } return list; } [Benchmark] public List<int> ProcessInitializedList() { var list = new List<int>(BatchSize); for (int i = 0; i < BatchSize; i++) { list.Add(i); } return list; } } }
注意事项
- 方式2中必须返回List,否则JIT编译器可能会将无返回值的空操作代码优化掉,导致基准测试结果失真。
- 两种方案都能确保每次测试的独立性,避免内存溢出的同时,保证性能对比的准确性。
内容的提问来源于stack exchange,提问作者Salvatore Calla'
相关产品推荐
相关产品推荐

