DEV Community

Cover image for Pre-allocate Like a Pro
Sukhpinder Singh
Sukhpinder Singh

Posted on

Pre-allocate Like a Pro

I’ve been playing with C# 15 quite a bit this week, and after yesterday’s post about the new with() syntax I started thinking about something I’ve always struggled with — making code both clean and actually fast.

You know how it goes. You write a quick list, start adding things in a loop, and everything works fine… until your data set grows and suddenly you’re wondering why things feel sluggish. I’ve been guilty of this more times than I care to admit.

So I decided to do a quick experiment.

I created a list with 100,000 items three different ways and timed each one. Nothing fancy, just my laptop and a stopwatch. The results surprised me a little.

Here’s what I tried:

First, the way I used to write it without thinking twice:

List<int> items = new();
for (int i = 0; i < 100_000; i++)
    items.Add(i);
Enter fullscreen mode Exit fullscreen mode

Second, the version where I at least tried to be responsible:

List<int> items = new(100_000);
for (int i = 0; i < 100_000; i++)
    items.Add(i);
Enter fullscreen mode Exit fullscreen mode

And finally, the C# 15 version:

List<int> items = [with(capacity: 100_000), ..Enumerable.Range(0, 100_000)];
Enter fullscreen mode Exit fullscreen mode

Day 2 Mini-Challenge

If you have ten minutes, throw together a small console app that runs all three and prints the times. Don’t make it perfect — just something simple and honest.

Here’s the little program I ended up with:

using System.Diagnostics;

Console.WriteLine("Testing pre-allocation in C# 15");

const int Size = 100_000;
var sw = Stopwatch.StartNew();

// No capacity at all
sw.Restart();
List<int> noCap = new();
for (int i = 0; i < Size; i++) noCap.Add(i);
Console.WriteLine($"No capacity          : {sw.ElapsedMilliseconds} ms");

// Old-school capacity
sw.Restart();
List<int> old = new(Size);
for (int i = 0; i < Size; i++) old.Add(i);
Console.WriteLine($"Traditional capacity : {sw.ElapsedMilliseconds} ms");

// New with() syntax
sw.Restart();
List<int> modern = [with(capacity: Size), ..Enumerable.Range(0, Size)];
Console.WriteLine($"C# 15 with(capacity) : {sw.ElapsedMilliseconds} ms");
Enter fullscreen mode Exit fullscreen mode

When I ran it a few times, the with() version kept coming out on top. Sometimes the difference wasn’t huge, but it was consistently faster, and honestly the code just feels better to look at.

I didn’t expect to get this excited about something as basic as pre-allocating memory, but here we are.


— A regular developer who still geeks out over this stuff

Top comments (0)