c# - linkedList.find() 中的意外 gc 分配行为
问题描述
众所周知,如果我们将值类型变量与null进行比较,会导致GC alloc导致装箱:
{
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(Deep Profile Enable) .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);
}
}
}
unity profiler 显示
TestGC 方法导致每帧 200Byte GC Alloc。
list.Find 方法导致每帧 0Byte GC Alloc。
解决方案
似乎LinkedList<T>.Find
(https://referencesource.microsoft.com/#System/compmod/system/collections/generic/linkedlist.cs,74e4e6394382badc,references)
用于EqualityComparer<T>
比较值,而后者又使用IEquatable<T>.Equals(T)
(https://docs.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。
推荐阅读
- reactjs - 从 ReactJS 中的功能组件更改类组件的状态
- azure - 有没有办法使用 Azure SDK 创建第 2 代 VM?
- flutter - Dart (Flutter) 的 Java 的 @SuppressWarnings("SpellCheckingInspection") 的模拟
- java - 为什么我的 inteliJ java eneterprise 项目看起来不一样?
- python - 如何在 discord.py 的 cog 中使用 Client?
- javascript - 在页面加载时使用单选按钮访问默认选择的行中的单个列
- c++ - Spix - Qt UI 测试框架构建
- kubernetes - 为什么 ReadWriteOnce 在不同的节点上工作?
- javascript - 在 mako 模板的新窗口中打开图像
- c# - 为什么要使用带有接口约束的泛型?