Copying a collection: ToList vs ToArray
It's common to use ToList()
or ToArray()
to copy a collection to a new collection. I've seen many comments on the web about which one is the most performant without any proof. So, it was time to run a benchmark.
C#
[MemoryDiagnoser]
public class CloneCollectionBenchmark
{
private byte[] _array = null!;
[Params(1, 10, 1_000, 10_000)]
public int Size { get; set; }
[GlobalSetup]
public void Setup()
{
_array = Enumerable.Range(0, Size).Select(i => (byte)i).ToArray();
}
[Benchmark]
public void Array_ToArray() => _array.ToArray();
[Benchmark]
public void Array_ToList() => _array.ToList();
[Benchmark]
public void Enumerable_ToArray() => AsEnumerable(_array).ToArray();
[Benchmark]
public void Enumerable_ToList() => AsEnumerable(_array).ToList();
// Avoid optimizations as ToList or ToArray cannot know
// the number of items in the collection to clone
IEnumerable<T> AsEnumerable<T>(IEnumerable<T> collection)
{
foreach (var item in collection)
yield return item;
}
}
INI
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
AMD Ryzen 7 5800X, 1 CPU, 16 logical and 8 physical cores
.NET SDK=6.0.100
[Host] : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
DefaultJob : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
Method | Size | Mean | Error | StdDev | Gen 0 | Gen 1 | Allocated |
---|---|---|---|---|---|---|---|
Array_ToArray | 1 | 18.14 ns | 0.201 ns | 0.188 ns | 0.0019 | - | 32 B |
Array_ToList | 1 | 20.91 ns | 0.421 ns | 0.394 ns | 0.0038 | - | 64 B |
Enumerable_ToArray | 1 | 55.16 ns | 0.845 ns | 0.790 ns | 0.0091 | - | 152 B |
Enumerable_ToList | 1 | 45.69 ns | 0.911 ns | 1.217 ns | 0.0091 | - | 152 B |
Array_ToArray | 10 | 18.14 ns | 0.383 ns | 0.536 ns | 0.0024 | - | 40 B |
Array_ToList | 10 | 21.53 ns | 0.427 ns | 0.420 ns | 0.0043 | - | 72 B |
Enumerable_ToArray | 10 | 147.84 ns | 2.978 ns | 3.429 ns | 0.0134 | - | 224 B |
Enumerable_ToList | 10 | 133.48 ns | 2.239 ns | 2.199 ns | 0.0134 | - | 224 B |
Array_ToArray | 1000 | 56.60 ns | 1.115 ns | 1.982 ns | 0.0612 | - | 1,024 B |
Array_ToList | 1000 | 65.12 ns | 1.318 ns | 1.410 ns | 0.0631 | 0.0002 | 1,056 B |
Enumerable_ToArray | 1000 | 6,868.17 ns | 107.927 ns | 100.955 ns | 0.1450 | - | 2,504 B |
Enumerable_ToList | 1000 | 7,222.47 ns | 111.929 ns | 104.698 ns | 0.1373 | - | 2,384 B |
Array_ToArray | 10000 | 403.56 ns | 10.100 ns | 28.651 ns | 0.5984 | - | 10,024 B |
Array_ToList | 10000 | 391.92 ns | 7.772 ns | 19.065 ns | 0.6003 | 0.0210 | 10,056 B |
Enumerable_ToArray | 10000 | 67,017.62 ns | 1,159.196 ns | 1,084.313 ns | 1.5869 | - | 27,112 B |
Enumerable_ToList | 10000 | 65,375.11 ns | 1,246.528 ns | 1,224.257 ns | 1.9531 | 0.1221 | 33,200 B |
If you only plan to iterate the result collection, you should use ToArray()
. Indeed, foreach
will be faster on an array than on a List<T>
.
C#
foreach(var item in enumerable.ToArray())
{
// ...
}
// Iterate a List<T> could be a few times slower than T[]
foreach(var item in enumerable.ToList())
{
// ...
}
Method | Size | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Allocated |
---|---|---|---|---|---|---|---|---|
ToArray_Foreach | 10000 | 2,671.84 ns | 42.267 ns | 39.537 ns | 2,666.25 ns | 0.5951 | - | 10,024 B |
ToList_Foreach | 10000 | 7,958.46 ns | 261.928 ns | 772.300 ns | 7,523.37 ns | 0.5951 | 0.0153 | 10,056 B |
#Conclusion
There is no significant difference between ToArray()
and ToList()
for most of the use-cases! But, it could be better to use ToArray()
if the only use case is to iterate the result collection.
#Additional resources
- Benchmark project
- Comparing implementations with BenchmarkDotnet
- [System.Linq] Performance: .ToList() counter-intuitively slower than .ToArray()
Do you have a question or a suggestion about this post? Contact me!
Enjoy this blog?💖 Sponsor on GitHub