OutOfMemoryException在使用BenchmarkDotNet比较.NET列表初始化与未初始化时发生。

huangapple go评论62阅读模式
英文:

OutOfMemoryException when comparing .NET list initialized vs not initialized one using BenchmarkDotNet

问题

我想创建一个基准测试,展示初始化和未初始化的 .net 列表之间性能差异,但我遇到了一些问题。我尝试了不同的方法来编写这个基准测试,但都没有成功。

每次运行代码时,我都会得到以下错误信息:

System.OutOfMemoryException: 数组维度超出了支持的范围

ListInitializationBenchmark.cs

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; }

        [GlobalSetup]
        public void GlobalSetup()
        {
            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);
            }
        }
    }
}

有关如何解决这个问题的任何想法吗?

英文:

I want to create a benchmark showing the difference in performance between an initialized and an uninitialized .net list, but I'm having some trouble. I tried different ways of writing this benchmark but without success.
Every time I run the code, I get the following:

System.OutOfMemoryException: Array dimensions exceeded supported range

ListInitializationBenchmark.cs

using BenchmarkDotNet.Attributes;

namespace list_benchmark
{
    public class ListInitializationBenchmark
    {
        private List<int> notInitializedList; // Not initialized list
        private List<int> initializedList; // Initialized list with capacity

        [Params(1000, 10000, 100000)]
        public int BatchSize { get; set; }

        [GlobalSetup]
        public void GlobalSetup()
        {
            notInitializedList = new List<int>(); // Not initialized list
            initializedList = new List<int>(BatchSize); // Initialized list with capacity
        }

        [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);
            }
        }
    }
}

Any idea on how can I resolve this problem?

答案1

得分: 5

BenchmarkDotNet 会运行你的代码数千次,以获得对代码执行时间的良好指示。然而,你的代码对于每次执行都使用相同的列表实例,这意味着它会很快耗尽空间。你需要将列表及其初始化放在各个测试内部,或者更改设置以在每次迭代时执行。例如:

[Benchmark]
public void ProcessNotInitializedList()
{
    List<int> notInitializedList = new List<int>();

    for (int i = 0; i < BatchSize; i++)
    {
        notInitializedList.Add(i);
    }
}

[Benchmark]
public void ProcessInitializedList()
{
    List<int> initializedList = new List<int>(BatchSize);

    for (int i = 0; i < BatchSize; i++)
    {
        initializedList.Add(i);
    }
}

或者这样:

[IterationSetup] // Iteration, not global setup
public void GlobalSetup()
{
    notInitializedList = new List<int>(); // 未初始化的列表
    initializedList = new List<int>(BatchSize); // 带有容量的已初始化列表
}
英文:

BenchmarkDotNet will run your code thousands of times to get a good indication of how long it takes. However, your code uses the same instance of the list for each execution meaning it will very quickly run out of space. You need to keep the list and its initialisation inside the individual tests or change your setup to be execute per iteration. For example:

[Benchmark]
public void ProcessNotInitializedList()
{
	List&lt;int&gt; notInitializedList = new List&lt;int&gt;();

	for (int i = 0; i &lt; BatchSize; i++)
	{
		notInitializedList.Add(i);
	}
}

[Benchmark]
public void ProcessInitializedList()
{
	List&lt;int&gt; initializedList = new List&lt;int&gt;(BatchSize);

	for (int i = 0; i &lt; BatchSize; i++)
	{
		initializedList.Add(i);
	}
}

Or this:

[IterationSetup] // Iteration, not global setup
public void GlobalSetup()
{
    notInitializedList = new List&lt;int&gt;(); // Not initialized list
    initializedList = new List&lt;int&gt;(BatchSize); // Initialized list with capacity
}

huangapple
  • 本文由 发表于 2023年5月21日 22:58:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76300520.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定