In my article titled Everything You Want to Know About the Record Type in .NET 5… But Were Afraid to Ask that I wrote in early 2021, I introduced readers to the new record type introduced in .NET 5 and why, as a class author, I like it. In this article, I will drill down into the performance using the record type.
For all the examples in this article, the record I am using for comparison is PersonRecord and the Person (POCO) class in my OSS assembly that I use for testing. Both have the same properties and data validation.
Creating a Record Type in Memory
First, let us look at the performance difference creating a normal Person object compared to a PersonRecord object. Depending on if you are using .NET 5 or 6, overall, Person is more performant. But, in .NET 6, the speed is much better.
Comparing Objects Using ==
Now, let's look at comparing objects using ==. As you can see below, Person is much more performant than PersonRecord.
Comparing Objects Using CompareTo()
If you compare objects using CompareTo(), then the results below are different depending on what version of .NET you are using.
Generating a HashCode
For this test, the Person type overrides GetHashCode() and uses all the properties for the type. For the PersonRecord, it is using the GetHashCode() generated by the record.
Sorting
I would guess that most developers sort collection using the Sort() method for the List<T> type. Let’s look at the performance results for this scenario.
Benchmark Results
Below are the benchmark results for Sort().
As you can easily see, sorting using Sort() for the PersonRecord type is slightly faster than using the Person type.
Sorting Using a Delegate
When sorting a collection of Person or PersonRecord using a delegate, the code looks like this:
collection.Sort(delegate (PersonRecord p1, PersonRecord p2)
{
return p1.LastName.CompareTo(p2.LastName);
});
Benchmark Results
Below are the benchmark results for sorting with a delegate.
As you can see, the performance is close and shows .NET 6 is slightly faster.
Sorting Using Enumerable.Reverse()
If you need to reverse the sorting of a collection, most developers might use Enumerable.Reverse(). Let’s look at the performance of this method for the record type.
Benchmark Results
As you can see, in this case, Person is slightly faster, but for some reason, the performance is not as good as it was in .NET 5.
Sorting Using CompareTo()
When sorting a collection of Person or PersonRecord using the CompareTo() method, the code looks like this:
collection.Sort((p1, p2) => p1.LastName.CompareTo(p2.LastName));
Benchmark Results
Below are the benchmark results for sorting using CompareTo().
As you can see, the performance using CompareTo(), the PersonRecord is faster. The Person object allocates 136 – 20,050 bytes in memory, while the PersonRecord allocates 0 bytes.
Sorting Using Enumerable OrderBy(), OrderByDecending(), ThenBy(), ThenByDecending
In the Enumerable type, there are three methods to order a collection. They are OrderBy(), OrderByDecending and ThenByDecending(). Here are examples of all three.
var list = collection.OrderBy(p => p.LastName).ToList();
var list = collection.OrderByDescending(p => p.LastName).ToList();
var list = collection.OrderBy(p => p.LastName).ThenBy(p => p.FirstName).ToList();
var list = collection.OrderBy(p => p.LastName).ThenByDescending(p => p.FirstName).ToList();
Benchmark Results
Person is slightly faster, and both allocated about the same amount of memory.
PersonRecord is slightly faster, and both allocated about the same amount of memory.
Person is slightly faster, and both allocated about the same amount of memory.
PersonRecord is slightly faster, and both allocated about the same amount of memory.
Serializing & Deserializing a Collection from JSON
For this example, I used the serializer in System.Text.Json and the Newtonsoft.Json NuGet package. Serialization is used a lot in programming, especially if the type is returned from or to an API service.
As you can see, the Person type performs better when serializing to JSON. One thing to note is that the Newtonsoft library allocates about double the KB in memory compared to the JsonSerializer.
As you can see, the Person type performs better when de-serializing from JSON. One thing to note is that the Newtonsoft library allocates about double the KB in memory compared to the JsonSerializer.
Summary
The purpose of this article is to help you decide to use a POCO class or a record class when you are thinking about performance over ease of use. The record type does help us create common methods for the type, but some of that comes with a performance hit. I hope that the runtime team at Microsoft will continue to work on the performance for the record type (since I personally really like it).
My next article will show performance differences between the POCO class, record types, and structures. If you have any comments or suggestions, please comment below.