2

Recently, I've been working in performance/memory optimization and have stucked in the empty array initialization which uses generic method to initialize empty array:

Code implementation of generic empty array class:

    public static class EmptyArray<T>
    {
        public static readonly T[] Instance;

        static EmptyArray()
        {
            Instance = new T[0];
        }
    }

So, whenever creating empty array of any type,it has been called as like:

var emptyStringArray = EmptyArray<string>.Instance;

Such empty array declaration has been done in many places of codebase. I am confused how would it be differs in performance while using :

var emptyStringArray = new string[0];

I've asked to above code author and he has replied me :

Basically, all empty arrays are readonly, and are equal to one another, which means that you can use the same instance (which will be created lazily on demand during run-time)… That should reduce the total number of allocations, reduce memory usage and GC pressure, and should result in some improvement

Still, I am not able to understand how would EmptyArray Instance boost the performance in array declaration.

Is there any performance difference in code using following approach :

1st Approach :

var emptyStrArr = EmptyArray<string>.Instance;
var emptyFooArr = EmptyArray<Foo>.Instance;
var emptyBarArr = EmptyArray<Bar>.Instance;

2nd Approach :

var emptyStrArr = new string[0];
var emptyFooArr = new Foo[0];
var emptyBarArr = new Bar[0];
1

3 Answers 3

1

In the first code the static constructor is executed only once.So you are just creating one array and using it all the time. In the second code you are creating an array instance each time. That's the difference.

You can see it more cleary by changing the constructor:

static EmptyArray()
{
   Instance = new T[0];
   Console.WriteLine("Array of "+ typeof(T) + " is created.");
}

var s = EmptyArray<string>.Instance;
s = EmptyArray<string>.Instance;
s = EmptyArray<string>.Instance;

var i = EmptyArray<int>.Instance;
i = EmptyArray<int>.Instance;

// output:
// Array of System.String is created.
// Array of System.Int32 is created.
Sign up to request clarification or add additional context in comments.

7 Comments

Although this could be made even more efficient without the static constructor... just with public static readonly T[] Instance = new T[0];. There's be fewer guarantees of the timing, but it would be slightly more efficient. (I'd probably use a property myself, but that shouldn't affect things.)
It's not only creating empty string array but also other type empty array. What'll be case if creating different array like this: var emptyStrArr = EmptyArray<string>.Instance; var emptyFooArr = EmptyArray<Foo>.Instance; var emptyBarArr = EmptyArray<Bar>.Instance;
@JonSkeet : Can you elaborate on "fewer guarantees of the timing"?
@akash88 an instance will be created for each type once in the first time. then if you use the same type you will get the previously created instance instead of a new one
@Selman22 : Does not that mean var emptyStrArr = EmptyArray<string>.Instance; var emptyFooArr = EmptyArray<Foo>.Instance; var emptyBarArr = EmptyArray<Bar>.Instance; is same as var emptyStrArr = new string[0]; var emptyFooArr = new Foo[0]; var emptyBarArr = new Bar[0];
|
0

This:

var emptyStringArray = new string[0];

Creates a new instance of an empty string array every time its called, with all the associated memory allocation overhead, whereas this:

public static class EmptyArray<T>
    {
        public static readonly T[] Instance;

        static EmptyArray()
        {
            Instance = new T[0];
        }
    }

Only ever creates a single instance of the empty string array, regardless of how many times you call the Instance field.

1 Comment

Doesn't that mean var emptyStrArr = EmptyArray<string>.Instance; var emptyFooArr = EmptyArray<Foo>.Instance; var emptyBarArr = EmptyArray<Bar>.Instance; is same as var emptyStrArr = new string[0]; var emptyFooArr = new Foo[0]; var emptyBarArr = new Bar[0];
0

jus to illustrate a bit how this can boost performance and memory you can try this

using System;

namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
            var str = EmptyArray<string>.Instance;
            var intTest = EmptyArray<int>.Instance;
            var intTest1 = EmptyArray<int>.Instance;  
            var str1 = EmptyArray<string>.Instance;
            Console.WriteLine(str.GetType());
            Console.WriteLine(intTest.GetType());
            if (ReferenceEquals(str,str1))
            {
                Console.WriteLine("References are equals");
            }
            if (ReferenceEquals(intTest,intTest1))             
            {
                Console.WriteLine("References are equals");
            }

        }
    }

    public static class EmptyArray<T>
    {
        public static readonly T[] Instance;

        static EmptyArray()
        {
            Instance =  new T[0];
        }
    }
}

you can see that no other allocation is needed even for value type and given that allocation and destruction of objects it's time and memory consuming you can enhance your code by doing this

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.