Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

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

Select an option

Save udlose/fe2a25d05b7f2eadee25fb70d9946df7 to your computer and use it in GitHub Desktop.
.NET Benchmark and Results for comparing iteration using foreach vs for over ArrayList containing Reference Type
using System;
using System.Collections;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Engines;
using BenchmarkDotNet.Running;
[MemoryDiagnoser]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
[CategoriesColumn]
public class IterationBenchmarks
{
[Params(1_000, 10_000, 50_000)]
public int Count;
private ArrayList _arrayList = null;
private Consumer _consumer = null;
[GlobalSetup]
public void GlobalSetup()
{
_arrayList = new ArrayList(Count);
for (int i = 0; i < Count; i++)
{
IPerson p = new Person(i, $"Dwight Schrute{i}");
_arrayList.Add(p); // boxed
}
// Create once and reuse, so you don't benchmark Consumer construction
_consumer = new Consumer();
}
[Benchmark(Baseline = true, Description = "ArrayList<Person> foreach")]
public void ArrayList_Foreach()
{
foreach (object item in _arrayList)
{
IPerson p = (Person)item; // unbox
_consumer.Consume(p);
}
}
[Benchmark(Description = "ArrayList<Person> for")]
public void ArrayList_For()
{
for (int i = 0; i < _arrayList.Count; i++)
{
IPerson value = (Person)_arrayList[i]; // indexer returns object -> unbox
_consumer.Consume(value);
}
}
[Benchmark(Description = "ArrayList<Person> for (with hoisted Count property)")]
public void ArrayList_For_Hoisted_Count()
{
int count = _arrayList.Count; // hoist Count to avoid virtual dispatch
for (int i = 0; i < count; i++)
{
IPerson value = (Person)_arrayList[i]; // indexer returns object -> unbox
_consumer.Consume(value);
}
}
}
public static class Program
{
public static void Main(string[] args)
{
IConfig config = DefaultConfig.Instance
.WithOption(ConfigOptions.DisableOptimizationsValidator, true)
.AddColumn(RankColumn.Arabic)
.AddColumn(StatisticColumn.OperationsPerSecond)
.WithSummaryStyle(
SummaryStyle.Default
.WithCultureInfo(System.Globalization.CultureInfo.GetCultureInfo("en-US"))
.WithRatioStyle(RatioStyle.Trend));
BenchmarkRunner.Run<IterationBenchmarks>(config);
}
}
public interface IPerson
{
int Compute();
}
public class Person : IPerson
{
public readonly int Id;
public readonly string Name;
public Person(int id, string name)
{
Id = id;
Name = name;
}
public int Compute()
{
// Cheap deterministic work; no allocations; good for net48 + net8.
Random rand = new Random();
int x = rand.Next() ^ (Id * 397);
x = (x << 5) | (int)((uint)x >> 27);
x = x * 31 + Id;
return x;
}
}
Run time: 00:03:06 (186.01 sec), executed benchmarks: 9
// * Summary *
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8390/25H2/2025Update/HudsonValley2)
12th Gen Intel Core i7-12800H 2.40GHz, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.300
[Host] : .NET 10.0.8 (10.0.8, 10.0.826.23019), X64 RyuJIT x86-64-v3
| Method | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------------------------------------------ |------ |-----------:|----------:|----------:|-------------:|--------:|-------:|----------:|------------:|
| 'ArrayList<Person> foreach' | 1000 | 2.467 μs | 0.0277 μs | 0.0259 μs | baseline | | 0.0038 | 48 B | |
| 'ArrayList<Person> for' | 1000 | 1.948 μs | 0.0258 μs | 0.0242 μs | 1.27x faster | 0.02x | - | - | NA |
| 'ArrayList<Person> for (with hoisted Count property)' | 1000 | 1.808 μs | 0.0187 μs | 0.0175 μs | 1.36x faster | 0.02x | - | - | NA |
| | | | | | | | | | |
| 'ArrayList<Person> foreach' | 10000 | 25.160 μs | 0.4454 μs | 0.4166 μs | baseline | | - | 48 B | |
| 'ArrayList<Person> for' | 10000 | 19.865 μs | 0.1721 μs | 0.1610 μs | 1.27x faster | 0.02x | - | - | NA |
| 'ArrayList<Person> for (with hoisted Count property)' | 10000 | 18.456 μs | 0.2452 μs | 0.2293 μs | 1.36x faster | 0.03x | - | - | NA |
| | | | | | | | | | |
| 'ArrayList<Person> foreach' | 50000 | 122.440 μs | 0.7770 μs | 0.6888 μs | baseline | | - | 49 B | |
| 'ArrayList<Person> for' | 50000 | 99.981 μs | 1.6674 μs | 1.5597 μs | 1.22x faster | 0.02x | - | 1 B | 49.00x less |
| 'ArrayList<Person> for (with hoisted Count property)' | 50000 | 92.652 μs | 1.2633 μs | 1.1817 μs | 1.32x faster | 0.02x | - | - | NA |
BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8390/25H2/2025Update/HudsonValley2)
12th Gen Intel Core i7-12800H 2.40GHz, 1 CPU, 20 logical and 14 physical cores
[Host] : .NET Framework 4.8.1 (4.8.9325.0), X64 RyuJIT VectorSize=256
DefaultJob : .NET Framework 4.8.1 (4.8.9325.0), X64 RyuJIT VectorSize=256
| Method | Count | Mean | Error | StdDev | Op/s | Ratio | RatioSD | Rank | Allocated | Alloc Ratio |
|------------------------------------------------------ |------ |-----------:|----------:|----------:|----------:|-------------:|--------:|-----:|----------:|------------:|
| 'ArrayList<Person> foreach' | 1000 | 7.946 μs | 0.1309 μs | 0.1455 μs | 125,857.0 | baseline | | 3 | 48 B | |
| 'ArrayList<Person> for' | 1000 | 3.131 μs | 0.0409 μs | 0.0383 μs | 319,378.7 | 2.54x faster | 0.05x | 2 | - | NA |
| 'ArrayList<Person> for (with hoisted Count property)' | 1000 | 2.246 μs | 0.0356 μs | 0.0297 μs | 445,322.5 | 3.54x faster | 0.08x | 1 | - | NA |
| | | | | | | | | | | |
| 'ArrayList<Person> foreach' | 10000 | 79.549 μs | 1.4641 μs | 1.3695 μs | 12,570.8 | baseline | | 3 | 48 B | |
| 'ArrayList<Person> for' | 10000 | 32.255 μs | 0.6338 μs | 0.8461 μs | 31,003.3 | 2.47x faster | 0.08x | 2 | - | NA |
| 'ArrayList<Person> for (with hoisted Count property)' | 10000 | 23.029 μs | 0.4540 μs | 0.6061 μs | 43,424.4 | 3.46x faster | 0.11x | 1 | - | NA |
| | | | | | | | | | | |
| 'ArrayList<Person> foreach' | 50000 | 386.441 μs | 5.1569 μs | 4.8238 μs | 2,587.7 | baseline | | 3 | 48 B | |
| 'ArrayList<Person> for' | 50000 | 162.241 μs | 2.8141 μs | 2.6323 μs | 6,163.7 | 2.38x faster | 0.05x | 2 | - | NA |
| 'ArrayList<Person> for (with hoisted Count property)' | 50000 | 116.088 μs | 0.7555 μs | 0.7067 μs | 8,614.2 | 3.33x faster | 0.04x | 1 | - | NA |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment