Unexpected gc alloc behavior in linkedList.find()

Viewed 171

As we all know that if we compare a value type variable with null,it will cause GC alloc cause of boxing:

{
    public class TestGeneric<T>{

        public static bool TestGC(T key)
        {
            return key == null;
        }
    }
    TestGeneric<int>.TestGC(10);
}

However, I found that the Find(T value) method of LinkedList(System.Collections.Generic) used same code like

public LinkedListNode<T> Find(T value)
{
    if (value != null)
    {
        //....
    }
}

But the calling like

//LinkedList<int> list;
list.Find(10);

will NOT cause any GC alloc.

I am really confused about that. Any body got an idea? Please Help.Thanks a lot.

====================

Test enviroment: Unity 2018, Unity Profiler(Deep Profile Enable) .Net Version:4.0

Here is my test code.

public class TestGeneric<T> {

    public static bool TestGC(T key)
    {
        return key == null;
    }
}

public class LinkedListTest : MonoBehaviour
{
    LinkedList<int> list = new LinkedList<int>();
    void Start()
    {
        for (int i = 0; i < 10; ++i)
        {
            list.AddLast(i);
        }
    }
    void Update()
    {
        for (int i = 0; i < 10; ++i)
        {
            TestGeneric<int>.TestGC(10);
        }
        for (int i = 0; i < 10; ++i)
        {
            list.Find(100);
        }
    }
}

The unity profiler shows

TestGC method caused 200Byte GC Alloc per frame.

list.Find method caused 0Byte GC Alloc per frame.

1 Answers

It seems that LinkedList<T>.Find (https://referencesource.microsoft.com/#System/compmod/system/collections/generic/linkedlist.cs,74e4e6394382badc,references)

uses EqualityComparer<T> to compare values, which in turn uses IEquatable<T>.Equals(T) (https://docs.microsoft.com/en-us/dotnet/api/system.iequatable-1.equals?view=netframework-4.8)

which

When the Equals method is called and the other argument is a strongly-typed object of type T. (If other is not of type T, the base Object.Equals(Object) method is called. Of the two methods, IEquatable.Equals offers slightly better performance.)

Since you are comparing int and they are the same type, the boxing does not occur since Object.Equals is not called.

Related