Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save udlose/9c6b91a8fb16a68a683c7cb6960d2d6a to your computer and use it in GitHub Desktop.

Select an option

Save udlose/9c6b91a8fb16a68a683c7cb6960d2d6a to your computer and use it in GitHub Desktop.
Benchmark comparing for vs foreach on List<int> using .NET 10 x64 vs .NET Framework 4.8.1 x64 RyuJIT vs .NET Framework 4.8.1 x86 LegacyJIT
[MemoryDiagnoser]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[Config(typeof(IterationBenchmarks_for_vs_foreach_ValueType.IterationBenchmarksConfig))]
public class IterationBenchmarks_for_vs_foreach_ValueType
{
[Params(1_000, 10_000, 50_000)]
public int Count;
private List<int> _listOfInt = null;
private Consumer _consumer = null;
[GlobalSetup]
public void GlobalSetup()
{
_listOfInt = new List<int>(Count);
Random random = new Random(42);
for (int i = 0; i < Count; i++)
{
_listOfInt.Add(random.Next());
}
_consumer = new Consumer();
}
[Benchmark(Description = "List<int> for with hoisted Count")]
// [MethodImpl(MethodImplOptions.NoInlining)]
public void List_For_With_Hoisted_Count()
{
int hoistedCount = _listOfInt.Count;
for (int i = 0; i < hoistedCount; i++)
{
int value = _listOfInt[i];
_consumer.Consume(value);
}
}
[Benchmark(Description = "List<int> for")]
// [MethodImpl(MethodImplOptions.NoInlining)]
public void List_For()
{
for (int i = 0; i < _listOfInt.Count; i++)
{
int value = _listOfInt[i];
_consumer.Consume(value);
}
}
[Benchmark(Baseline = true, Description = "List<int> foreach")]
// [MethodImpl(MethodImplOptions.NoInlining)]
public void List_Foreach()
{
foreach (int item in _listOfInt)
{
_consumer.Consume(item);
}
}
private class IterationBenchmarksConfig : ManualConfig
{
public IterationBenchmarksConfig()
{
SummaryStyle = BenchmarkDotNet.Reports.SummaryStyle.Default.WithRatioStyle(RatioStyle.Trend);
}
}
}
public static class Program
{
public static void Main(string[] args)
{
BenchmarkRunner.Run<IterationBenchmarks_for_vs_foreach_ValueType>();
}
}
// Global total time: 00:08:13 (493.27 sec), executed benchmarks: 9
//
// * Summary *
//
// BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.7840/25H2/2025Update/HudsonValley2)
// AMD Ryzen 9 7945HX with Radeon Graphics 2.50GHz, 1 CPU, 32 logical and 16 physical cores
//
// [Host] : .NET Framework 4.8.1 (4.8.9221.0), X64 RyuJIT VectorSize=256
// DefaultJob : .NET Framework 4.8.1 (4.8.9221.0), X64 RyuJIT VectorSize=256
//
//| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
//|----------------------------------- |------ |------------:|------------:|------------:|-------------:|--------:|
//| 'List<int> for with hoisted Count' | 1000 | 648.8 ns | 7.56 ns | 6.71 ns | 2.42x faster | 0.14x |
//| 'List<int> for' | 1000 | 811.2 ns | 15.92 ns | 18.33 ns | 1.94x faster | 0.12x |
//| 'List<int> foreach' | 1000 | 1,570.0 ns | 31.19 ns | 87.47 ns | baseline | |
//| | | | | | | |
//| 'List<int> for with hoisted Count' | 10000 | 7,237.9 ns | 143.83 ns | 280.52 ns | 1.98x faster | 0.10x |
//| 'List<int> for' | 10000 | 8,271.9 ns | 164.82 ns | 437.08 ns | 1.73x faster | 0.11x |
//| 'List<int> foreach' | 10000 | 14,292.0 ns | 285.05 ns | 528.36 ns | baseline | |
//| | | | | | | |
//| 'List<int> for with hoisted Count' | 50000 | 35,703.6 ns | 712.24 ns | 926.12 ns | 1.95x faster | 0.08x |
//| 'List<int> for' | 50000 | 39,753.5 ns | 790.27 ns | 2,216.00 ns | 1.76x faster | 0.11x |
//| 'List<int> foreach' | 50000 | 69,590.0 ns | 1,388.87 ns | 2,320.49 ns | baseline | |
// Global total time: 00:08:50 (530.02 sec), executed benchmarks: 9
//
// * Summary *
//
// BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.7840/25H2/2025Update/HudsonValley2)
// AMD Ryzen 9 7945HX with Radeon Graphics 2.50GHz, 1 CPU, 32 logical and 16 physical cores
//
// [Host] : .NET Framework 4.8.1 (4.8.9221.0), X86 LegacyJIT
// DefaultJob : .NET Framework 4.8.1 (4.8.9221.0), X86 LegacyJIT
//
//| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
//|----------------------------------- |------ |------------:|------------:|------------:|-------------:|--------:|
//| 'List<int> for with hoisted Count' | 1000 | 617.7 ns | 12.00 ns | 17.59 ns | 2.52x faster | 0.10x |
//| 'List<int> for' | 1000 | 714.8 ns | 13.89 ns | 18.54 ns | 2.18x faster | 0.08x |
//| 'List<int> foreach' | 1000 | 1,555.4 ns | 29.82 ns | 39.81 ns | baseline | |
//| | | | | | | |
//| 'List<int> for with hoisted Count' | 10000 | 7,189.5 ns | 143.07 ns | 384.36 ns | 2.37x faster | 0.18x |
//| 'List<int> for' | 10000 | 8,192.6 ns | 162.94 ns | 367.79 ns | 2.07x faster | 0.15x |
//| 'List<int> foreach' | 10000 | 16,965.2 ns | 338.25 ns | 948.50 ns | baseline | |
//| | | | | | | |
//| 'List<int> for with hoisted Count' | 50000 | 36,505.7 ns | 889.86 ns | 2,581.66 ns | 2.30x faster | 0.20x |
//| 'List<int> for' | 50000 | 39,884.4 ns | 855.76 ns | 2,509.80 ns | 2.10x faster | 0.17x |
//| 'List<int> foreach' | 50000 | 83,468.6 ns | 1,664.93 ns | 4,176.99 ns | baseline | |
NOTE that multiple runs sometimes produced results where foreach was slightly faster.
I attribute this to the measurement noise of StdDev.
This flip-flop did NOT happen in the .NET Framework 4.8.1 benchmark results
// Global total time: 00:07:23 (443.34 sec), executed benchmarks: 9
//
// * Summary *
//
// BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.7840/25H2/2025Update/HudsonValley2)
// AMD Ryzen 9 7945HX with Radeon Graphics 2.50GHz, 1 CPU, 32 logical and 16 physical cores
//
// .NET SDK 10.0.103
// [Host] : .NET 10.0.3 (10.0.3, 10.0.326.7603), X64 RyuJIT x86-64-v4
//
//| Method | Count | Mean | Error | StdDev | Ratio | RatioSD |
//|----------------------------------- |------ |------------:|----------:|------------:|-------------:|--------:|
//| 'List<int> for with hoisted Count' | 1000 | 647.9 ns | 12.86 ns | 27.96 ns | 1.01x slower | 0.08x |
//| 'List<int> for' | 1000 | 865.4 ns | 17.15 ns | 47.23 ns | 1.34x slower | 0.12x |
//| 'List<int> foreach' | 1000 | 647.3 ns | 14.97 ns | 43.90 ns | baseline | |
//| | | | | | | |
//| 'List<int> for with hoisted Count' | 10000 | 6,530.4 ns | 128.99 ns | 242.27 ns | 1.06x slower | 0.06x |
//| 'List<int> for' | 10000 | 7,874.7 ns | 156.28 ns | 440.78 ns | 1.28x slower | 0.09x |
//| 'List<int> foreach' | 10000 | 6,180.4 ns | 119.06 ns | 287.55 ns | baseline | |
//| | | | | | | |
//| 'List<int> for with hoisted Count' | 50000 | 32,936.5 ns | 950.65 ns | 2,803.02 ns | 1.04x faster | 0.12x |
//| 'List<int> for' | 50000 | 41,521.8 ns | 826.11 ns | 2,041.95 ns | 1.23x slower | 0.11x |
//| 'List<int> foreach' | 50000 | 34,022.1 ns | 857.86 ns | 2,529.41 ns | baseline | |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment