Performance in .NET – Part 1

Updated: thanks, Paulo Morgado!

Introduction

Along the years I wrote a couple of posts about performance in the .NET world. Some were more tied to specific frameworks, such as NHibernate or Entity Framework, while others focus on the generic bits. In this series of posts I will summarize my findings on .NET in general, namely:

  • Object creation (this post)
  • Object cloning
  • Value Types versus Reference Types
  • Collections
  • Possibly other stuff

I won’t be talking about object serialization, as there are lots of serializers out there, each with its pros and cons. In general, I’d say either serializing to and from JSON or from a binary format seem to be the most demanded ones, and each has quite a few options, either provided by Microsoft or from third parties. The actual usage also affects what we want – is it a general-purpose serializer or one for a particular usage, that needs classes prepared accordingly? Let’s keep it out of this discussion.

As always, feel free to reach out to me if you want to discuss any of these! So, lets start with object creation.

Object Creation

Let’s start with object creation and by defining our purpose: we want to be able to create object instances of a certain type as fast as possible. We have a couple of strategies:

Let’s cover them all one by one.

Using the new Operator

This is the most obvious (and fast), but does not play well with dynamic instantiation, meaning, the type to instantiate needs to be hardcoded. I call it direct instantiation, and it goes as this (you know, you know…):

var obj = new Xpto();

This should be the baseline for all performance operations, as it should offer the best possible performance.

Using Reflection

Here I’m caching the public parameterless constructor and invoking it, then casting the result to the target type:

var ci = typeof(Xpto).GetConstructor(Type.EmptyTypes);<br />var obj = ci.Invoke(null) as Xpto;

Just avoid getting the constructor over and over again, do it once for each type then cache it somewhere.

Using FormatterServices.GetUninitializedObject

The GetUninitializedObject method is used internally by some serializers and what it does is, it merely allocates memory for the target type and zeroes all of its fields, without actually running any constructor. This has the effect that any explicitly declared field and property values will be lost, so use with care. It is available in .NET Core:

var obj = FormatterServices.GetUninitializedObject(typeof(Xpto)) as Xpto;

Pay attention that none of the constructors of your type are executed, and no fields or properties have their initial values set, other than the default value for each type (null for reference types, the default for value types).

Using System.Reflection.Emit code generation

This one uses the code generation library that is built-in with .NET (but not .NET Core, for the time being):

var m = new DynamicMethod(string.Empty, typeof(object), null, typeof(Xpto), true);<br />var ci = typeof(Xpto).GetConstructor(Type.EmptyTypes);<br />var il = m.GetILGenerator();<br />il.Emit(OpCodes.Newobj, ci);<br />il.Emit(OpCodes.Ret);<br />var creator = m.CreateDelegate(typeof(Func<object>)) as Func<object>;<br />var obj = creator() as Xpto;

As you can see, we are just generating code for a dynamic method, providing a simple content that does “new Xpto()”, and execute it.

Using Activator.CreateInstance

This is essentially a wrapper around the reflection code I’ve shown earlier, with the drawback that it does not cache each types’ public parameterless constructor:

var obj = Activator.CreateInstance(typeof(Xpto)) as Xpto;

Using LINQ expressions

The major drawback of this approach is the time it takes to build the actual code (the first call to Compile). After that, it should be fast:

var ci = typeof(Xpto).GetConstructor(Type.EmptyTypes);<br />var expr = Expression.New(ci);<br />var del = Expression.Lambda(expr).Compile();<br />var obj = del.DynamicInvoke() as Xpto;

Of course, if you are to call this a number of times for the same type, it may be worth caching the constructor for each type.

Using Delegates

The LINQ expressions approach actually compiles to this one, but this is strongly typed:

Func<Xpto> del = () => new Xpto();<br />var obj = del();

Using Roslyn

This one is relatively new in .NET. As you may know, Microsoft now uses Roslyn to both parse and generate code dynamically. The scripting capabilities are made available through the Microsoft.CodeAnalysis.CSharp.Scripting NuGet package. The actual code for instantiating a class (or actually executing any code) dynamically goes like this:

var obj = CSharpScript.EvaluateAsync("new Xpto()").GetAwaiter().GetResult() as Xpto;

Do keep in mind that Roslyn is asynchronous by nature, so you need to wait for the result, also, do add the full namespace of your type, which I omitted for brevity. There are other APIs that allow you to compile code and reuse the compilation:

var script = CSharpScript.Create<Xpto>("new Xpto()", ScriptOptions.Default.AddReferences(typeof(Xpto).Assembly));<br />var runner = script.CreateDelegate();<br />var obj = runner().GetAwaiter().GetResult();

Conclusion

Feel free to run your tests, with a few iterations, and look at the results. Always compare with the normal way to create objects, the new operator. Do not forget the problems with each approach, like the need to cache something or any limitations on the instantiated object.

In my machine, for 1000 iterations, a couple times for the same run, I get these average results (elapsed ticks):

Technique Delay
Direct 0.148
FormatterServices.GetUninitializedObject 0.324
Activator.CreateInstance 0.296
Reflection 0.6
IL 0.557
LINQ Expression 4.085
Delegate 0.109
Roslyn 2400.796

Some of these may be surprising to you, as they were to me! It seems that reflection is not that much slower than direct instantiation as one might think… hmmm…

As usual, I’d love to hear your thoughts on this! More to come soon! Winking smile

C# Special Method Names

Introduction

You may not have realized that some of the patterns that you’ve been using for ages in your C# programs are based on conventions, rather than on a specific API. What I mean by this is, some constructs in C# are based on some magical methods with well-defined names which are not defined in any base class or interface, but yet just work. Let’s see what they are.

Enumerations

You are probably used to iterating through collections using the foreach statement. If you are, you may know that foreach actually wraps a call to a method called GetEnumerator, like the one that is defined by the IEnumerable and IEnumerable<T> interfaces. Thus, you might think, the magic occurs because the collection implements one or the two, but you would be wrong: it turns out that in order to iterate through a class using foreach all it takes is that the class exposes a public method called GetEnumerator that returns either a IEnumerator or a IEnumerator<T> instance. For example, this works:

public class Enumerable
{
    public IEnumerator GetEnumerator()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }
}

var e = new Enumerable();

foreach (int i in e) { /*...*/ }

As you see, there is no need to implement any of these interfaces, but it is a good practice, for example, because it gives you access to LINQ extension methods.

Deconstruction to Tuples

Tuples were introduce in C# 7. In a nutshell, they provide a way for us to return multiple values from a method:

(int x, int y) GetPosition()
{
    return (x: 10, y: 20);
}

Another option is to have a class deconstructed into a tuple. Say, for example, that we have a class like this:

public class Rectangle
{
    public int Height { get; set; }
    public int Width { get; set; }
}

We can have it deconstructed into a tuple, by providing one or more Deconstruct methods in this class:

public void Deconstruct(out int h, out int w)
{
    h = this.Height;
    w = this.Width;
}

Which allows you to write code like this:

var rectangle = new Rectangle { Height = 10, Width = 20 };
var (h, w) = rectangle;

You can implement multiple Deconstruct methods with different parameters, which must always be out. When you try to assign your class to a tuple, C# will try to find a Deconstruct method that matches the tuple’s declaration, or throw an exception if one cannot be found:

public void Deconstruct(out int perimeter, out int area, out bool square)
{
    perimeter = this.Width * 2 + this.Height * 2;
    area = this.Width * this.Height;
    square = this.Width == this.Height;
}

var (perimeter, area, square) = rectangle;

Collection Initialization

Since C# 6, we have a more concise syntax for initializing collections:

var strings = new List<string> { "A", "B", "C" };

The syntax to follow is an enumeration of items whose type matches the collection’s item type, inside curly braces, each separated by a comma. This is possible because there is a public Add method that takes a parameter of the appropriate type. What happens behind the scene is that the Add method is called multiple times, one for each item inside the curly braces. Meaning, this works too:

public class Collection : IEnumerable
{
    public IEnumerator GetEnumerator() => /* ... */
    public void Add(string s) { /* ... */ }
}

Notice that this collection offers a public Add method and needs to implement either IEnumerable or IEnumerable<T>, which, mind you, do not define an Add method. Having this, we can write:

var col = new Collection { "A", "B", "C" };

The magical Add method can have multiple parameters, like for dictionaries:

var dict = new Dictionary<string, int> { { "A", 1 }, { "B", 2 }, { "C", 3 } };

Each parameter will need to go inside it’s own set of curly braces.

What’s even funnier is, you can mix different Add methods with different parameters:

public void Add(int i) { /* ... */ }
public void Add(string s) { /* ... */ }

var col = new Collection { 1, 2, 3, "a", "b", "c" };

Conclusion

In this post I introduced the magical GetEnumerator, Deconstruct and Add methods. This was just for fun, the information here is probably useless, but, hey, it’s done! Winking smile