.NET Core, BenchmarkDotNet: for vs foreach performance
.NET Core, BenchmarkDotNet: for vs foreach performance
Categories:
3 minute read
So what is faster: looping through a List<> with for or with foreach?
Today I’ll show you how to use BenchmarkDotNet with .Net Core to answer that question.
Let’s start:
Create a folder for your new project
Open a command prompt an run:
mkdir benchmark.for
Create the project
cd benchmark.for
dotnet new console
Add the references to BenchmarkDotNet
dotnet add package BenchmarkDotNet -v 0.11.0
dotnet restore
Replace the contents of Program.cs with the following code
using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace benchmark
{
public class Program
{
public static void Main(string[] args)
{
// Use BenchmarkRunner.Run to Benchmark your code
var summary = BenchmarkRunner.Run<ForEachVsFor>();
}
}
// We are using .Net Core we are adding the CoreJobAttribute here.
[CoreJob(baseline: true)]
[RPlotExporter, RankColumn]
public class ForEachVsFor
{
private static Random random = new Random();
private List<int> list;
public static List<int> RandomIntList(int length)
{
int Min = 1;
int Max = 10;
return Enumerable
.Repeat(0, length)
.Select(i => random.Next(Min, Max))
.ToList();
}
// We wil run the the test for 3 diff list sizes
[Params(10, 100, 1000)]
public int N;
[GlobalSetup]
public void Setup()
{
list = RandomIntList(N);
}
// Foreach is ~2 times slower than for
[Benchmark]
public void Foreach()
{
int total = 0;
foreach (int i in list)
{
total += i;
}
}
// For is ~2 times faster than foreach
[Benchmark]
public void For()
{
int total = 0;
for (int i = 0; i < list.Count; i++)
{
total += list[i];
}
}
}
}
Run the application and interpret the results
Run the following command:
dotnet run -c release
after a while you should expect an output like the following:
// * Summary *
BenchmarkDotNet=v0.11.0, OS=Windows 10.0.17134.228 (1803/April2018Update/Redstone4)
Intel Core i5-6300U CPU 2.40GHz (Skylake), 1 CPU, 4 logical and 2 physical cores
Frequency=2437501 Hz, Resolution=410.2562 ns, Timer=TSC
.NET Core SDK=2.1.302
[Host] : .NET Core 2.1.2 (CoreCLR 4.6.26628.05, CoreFX 4.6.26629.01), 64bit RyuJIT
Core : .NET Core 2.1.2 (CoreCLR 4.6.26628.05, CoreFX 4.6.26629.01), 64bit RyuJIT
Job=Core Runtime=Core
Method | N | Mean | Error | StdDev | Median | Scaled | Rank |
-------- |----- |------------:|-----------:|------------:|------------:|-------:|-----:|
Foreach | 10 | 45.76 ns | 3.0062 ns | 8.8167 ns | 43.15 ns | 1.00 | 1 |
| | | | | | | |
For | 10 | 18.14 ns | 0.4040 ns | 0.3968 ns | 18.04 ns | 1.00 | 1 |
| | | | | | | |
Foreach | 100 | 503.16 ns | 9.9973 ns | 24.8968 ns | 501.49 ns | 1.00 | 1 |
| | | | | | | |
For | 100 | 149.56 ns | 3.6317 ns | 10.1238 ns | 147.41 ns | 1.00 | 1 |
| | | | | | | |
Foreach | 1000 | 2,611.51 ns | 51.7677 ns | 122.0225 ns | 2,596.29 ns | 1.00 | 1 |
| | | | | | | |
For | 1000 | 1,406.77 ns | 28.3726 ns | 82.3140 ns | 1,391.04 ns | 1.00 | 1 |
So as you can see for performs much better than foreach when looping through a List<>!!!
Try changing the int type for a class and then working with it inside the loop and check the results. You’ll know what to do next time you need your application to run fast!
Please find all the code used in this post here.
Hope it helps!