【发布时间】:2016-06-13 14:51:35
【问题描述】:
我有一个结构体作为键和类引用作为值的通用字典。
Dictionary<IntVector2, SpriteRenderer> tileRendererMap;
我通过坐标检索对渲染器的引用并将其更改如下:
tileRendererMap[tileCoord].color = Color.cyan;
每次我使用它都会产生 0.8KB 的垃圾。这是默认行为吗?我认为字典查找将是最高效的事情之一。我需要想办法解决这个问题,因为我正在为移动平台工作,它是一个关键系统。
任何想法我可能做错了什么或如何获得免分配查找?
在更多测试后编辑:
使用 int 作为键而不是我的自定义结构按预期工作。没有分配,没有问题,我认为使用 id 作为键并不奇怪。但是,对于我的游戏,我想将与特定图块关联的渲染器存储在网格中,它实际上不需要是任何类型的对象,因为我只关心网格位置。因此,我认为 IntVector2 可能是一个实用的标识符,但如果必须,我可以解决它。
使用我的结构时,我会得到分配,我使用 Unity3D Profiler 进行测量。它在 Dictionary_get_item 中报告 0.8KB,特别是 DefaultComparer.Equals()。显然这是一个装箱/拆箱问题,但即使我实现了自定义覆盖,它仍然会产生垃圾,只是比以前少一点。
我的基本结构实现:
public struct IntVector2
{
public int x, y;
public override bool Equals(object obj)
{
if (obj == null || obj is IntVector2 == false)
return false;
var data = (IntVector2)obj;
return x == data.x && y == data.y;
}
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode();
}
}
接受答案后编辑:
在通用字典中使用时我的结构的免分配版本。
public struct IntVector2 : IEquatable<IntVector2>
{
public int x;
public int y;
public IntVector2(int x, int y)
{
this.x = x;
this.y = y;
}
public bool Equals(IntVector2 other)
{
return x == other.x && y == other.y;
}
}
Dictionary 类使用 IEquatable 接口而不是 object 覆盖 Equals,这就是为什么我的第一个每次在搜索键时检查是否相等时,实现都会对其中一个值进行装箱。
【问题讨论】:
-
0.8kb 的垃圾应该会在需要时自动收集。
-
您如何确定创建了 0.8 kb 的垃圾?你分析过那些垃圾包含的类型吗?
-
它根本不会产生任何垃圾,您只是在 SpriteRenderer 对象上设置一个属性。 “颜色”不太可能是引用类型,甚至更不可能占用 800 个字节。你测量垃圾的方式有问题。
-
我正在使用 Unity 3D Profiler 进行测量。它在 dictionary_get_item 中报告分配,特别是在 DefaultComparer Equals 方法中。我现在正在测试是否可以通过更改比较器来获得不同的结果。
标签: c# dictionary garbage-collection