linkedList.find() 中意外的 gc alloc 行为



众所周知,如果我们将值类型变量与null进行比较,则会导致GC分配装箱的原因:

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

但是,我发现LinkedList(System.Collections.Generic(的Find(T value(方法使用了相同的代码,例如

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

但召唤喜欢

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

不会导致任何 GC 分配。

我对此感到非常困惑。有人有想法吗?请帮忙。非常感谢。

====

================测试环境:Unity 2018,Unity Profiler(深度配置文件启用(.Net 版本:4.0

这是我的测试代码。

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);
}
}
}

统一性能分析器显示

TestGC 方法导致每帧分配 200 字节 GC

列表。查找方法导致每帧分配 0 字节 GC

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

使用EqualityComparer<T>来比较值,而值又使用IEquatable<T>.Equals(T)(https://learn.microsoft.com/en-us/dotnet/api/system.iequatable-1.equals?view=netframework-4.8(

当调用 Equals 方法

并且另一个参数是 T 类型的强类型对象时(如果 other 不是 T 类型,则调用基 Object.Equals(Object( 方法。在这两种方法中,IEquatable.Equals提供了稍微好一点的性能。

由于您正在比较 int 并且它们是相同的类型,因此不会发生装箱,因为未调用 Object.Equals。

最新更新