From da251966549ecfefed885f75b802e8f579999189 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 13 Sep 2026 20:41:20 +0200 Subject: [PATCH] ArrayList vs List: add the boxing benchmark project --- .../ArrayListVsList/ArrayListVsList.sln | 34 +++++++ .../Benchmarks/Benchmarks.csproj | 14 +++ .../Benchmarks/BoxingBenchmark.cs | 99 +++++++++++++++++++ .../ArrayListVsList/Benchmarks/Program.cs | 4 + 4 files changed, 151 insertions(+) create mode 100644 collections-lists/ArrayListVsList/Benchmarks/Benchmarks.csproj create mode 100644 collections-lists/ArrayListVsList/Benchmarks/BoxingBenchmark.cs create mode 100644 collections-lists/ArrayListVsList/Benchmarks/Program.cs diff --git a/collections-lists/ArrayListVsList/ArrayListVsList.sln b/collections-lists/ArrayListVsList/ArrayListVsList.sln index 4a87186386..24680e4f7d 100644 --- a/collections-lists/ArrayListVsList/ArrayListVsList.sln +++ b/collections-lists/ArrayListVsList/ArrayListVsList.sln @@ -7,20 +7,54 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArrayListVsList", "ArrayLis EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {844DACC5-2552-4136-8EE4-EC215A721884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {844DACC5-2552-4136-8EE4-EC215A721884}.Debug|Any CPU.Build.0 = Debug|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Debug|x64.ActiveCfg = Debug|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Debug|x64.Build.0 = Debug|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Debug|x86.ActiveCfg = Debug|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Debug|x86.Build.0 = Debug|Any CPU {844DACC5-2552-4136-8EE4-EC215A721884}.Release|Any CPU.ActiveCfg = Release|Any CPU {844DACC5-2552-4136-8EE4-EC215A721884}.Release|Any CPU.Build.0 = Release|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Release|x64.ActiveCfg = Release|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Release|x64.Build.0 = Release|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Release|x86.ActiveCfg = Release|Any CPU + {844DACC5-2552-4136-8EE4-EC215A721884}.Release|x86.Build.0 = Release|Any CPU {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Debug|x64.ActiveCfg = Debug|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Debug|x64.Build.0 = Debug|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Debug|x86.Build.0 = Debug|Any CPU {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Release|Any CPU.Build.0 = Release|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Release|x64.ActiveCfg = Release|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Release|x64.Build.0 = Release|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Release|x86.ActiveCfg = Release|Any CPU + {4B4BE163-4AD2-4848-AAD5-AB2C0A5F4F95}.Release|x86.Build.0 = Release|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Debug|x64.ActiveCfg = Debug|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Debug|x64.Build.0 = Debug|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Debug|x86.ActiveCfg = Debug|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Debug|x86.Build.0 = Debug|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Release|Any CPU.Build.0 = Release|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Release|x64.ActiveCfg = Release|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Release|x64.Build.0 = Release|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Release|x86.ActiveCfg = Release|Any CPU + {FB7AABD4-ABF9-4D94-AD26-61A0DE6EA773}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/collections-lists/ArrayListVsList/Benchmarks/Benchmarks.csproj b/collections-lists/ArrayListVsList/Benchmarks/Benchmarks.csproj new file mode 100644 index 0000000000..f1f8bf88dc --- /dev/null +++ b/collections-lists/ArrayListVsList/Benchmarks/Benchmarks.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/collections-lists/ArrayListVsList/Benchmarks/BoxingBenchmark.cs b/collections-lists/ArrayListVsList/Benchmarks/BoxingBenchmark.cs new file mode 100644 index 0000000000..628e11119c --- /dev/null +++ b/collections-lists/ArrayListVsList/Benchmarks/BoxingBenchmark.cs @@ -0,0 +1,99 @@ +using System.Collections; +using BenchmarkDotNet.Attributes; + +namespace BoxingBench; + +// Measures the one claim the article argues from mechanism: List is faster than ArrayList +// because it does not box, so the effect is large for value types and small for reference types. +// Both collections are created with the final capacity, so the only allocation difference left +// is the boxing itself. +[MemoryDiagnoser] +public class BoxingBenchmark +{ + private const int N = 1000; + + private static readonly string[] Words = CreateWords(); + + private static string[] CreateWords() + { + var words = new string[N]; + for (var i = 0; i < N; i++) + { + words[i] = "item-" + i; + } + + return words; + } + + [Benchmark(Description = "ArrayList, 1000 int")] + public int ArrayListOfInt() + { + var collection = new ArrayList(N); + for (var i = 0; i < N; i++) + { + collection.Add(i); + } + + var sum = 0; + foreach (var item in collection) + { + sum += (int)item!; + } + + return sum; + } + + [Benchmark(Description = "List, 1000 int")] + public int ListOfInt() + { + var collection = new List(N); + for (var i = 0; i < N; i++) + { + collection.Add(i); + } + + var sum = 0; + foreach (var item in collection) + { + sum += item; + } + + return sum; + } + + [Benchmark(Description = "ArrayList, 1000 string")] + public int ArrayListOfString() + { + var collection = new ArrayList(N); + for (var i = 0; i < N; i++) + { + collection.Add(Words[i]); + } + + var total = 0; + foreach (var item in collection) + { + total += ((string)item!).Length; + } + + return total; + } + + [Benchmark(Description = "List, 1000 string")] + public int ListOfString() + { + var collection = new List(N); + for (var i = 0; i < N; i++) + { + collection.Add(Words[i]); + } + + var total = 0; + foreach (var item in collection) + { + total += item.Length; + } + + return total; + } +} diff --git a/collections-lists/ArrayListVsList/Benchmarks/Program.cs b/collections-lists/ArrayListVsList/Benchmarks/Program.cs new file mode 100644 index 0000000000..689c711d9c --- /dev/null +++ b/collections-lists/ArrayListVsList/Benchmarks/Program.cs @@ -0,0 +1,4 @@ +using BenchmarkDotNet.Running; +using BoxingBench; + +BenchmarkRunner.Run();