除了大约1k个实例经常运行自己的ContainsKey()
和ToString()
这一事实之外,我不得不提供更多详细信息。
位置只是我个人替换Unity Vector3
以满足我的需求:
[Serializable] public struct Location
{
public double X;
public double Y;
public double Z;
public Location(double x, double y, double z) : this()
{
X = x;
Y = y;
Z = z;
}
public override string ToString()
{
return String.Format("{0}, {1}, {2}", X, Y, Z);
}
}
(我知道我打破Structs
的某种规则..只是不确定如何以另一种方式实现我的需求。)
以下是Profiler运行的屏幕截图:
正如你所看到的,对于大多数时间线来说,它是稳定的,然后在我的实例达到大约1k(数量)之后突然发生(他们以100-250左右开始)CPU和内存由于似乎看起来很疯狂成为GC分配。我一直在寻找能够更好地清理的东西,但我发现甚至导致任何GC分配都是在我运行的时候:
if (_dictionary.ContainsKey(key)) {...}
以及使用以下命令重命名Unity GameObjects时
part.name = "Part: " + part.Location.ToString();
如果它仅仅涉及查找所需的不可避免的时间,那么Dictionaries
是否有任何替代方案往往运行速度更慢但导致GC分配更少,并且有更有效的方式{{} 1}} override
方法?
添加: 我的词典是关键:(我的个人结构)位置,值:类实例。
答案 0 :(得分:1)
将评论转化为答案......
您的ToString()
方法总是会创建一个新字符串,所以这并不奇怪。但是,您还使用字符串连接,因此您要创建两个新字符串。您可以通过内联ToString()
方法将其减少为1。例如,为简洁起见,使用C#6插值字符串:
var location = part.Location;
part.name = $"Part: {location.X}, {location.Y}, {location.Z}";
对于字典方面,有两个问题:
Equals
和GetHashCode
,其中可能表示该值正在装箱,以便调用ValueType
中的实现。我不是百分百肯定的;关于拳击的规则可能很复杂。IEquatable<T>
,因此非常可能会有任何Equals
来电。{/ li>
您可以轻松解决这两个问题:
[Serializable] public struct Location : IEquatable<Location>
{
public double X;
public double Y;
public double Z;
public Location(double x, double y, double z) : this()
{
X = x;
Y = y;
Z = z;
}
public override string ToString() => $"{X}, {Y}, {Z}";
public override bool Equals(object obj) =>
obj is Location loc && Equals(loc);
public bool Equals(Location other) =>
X == other.X && Y == other.Y && Z == other.Z;
public override int GetHashCode()
{
// Replace with whatever implementation you want
int hash = 17;
hash = hash * 23 + X.GetHashCode();
hash = hash * 23 + Y.GetHashCode();
hash = hash * 23 + Z.GetHashCode();
return hash;
};
}
(那是使用C#7语法,但是如果你使用现代版本的Unity和VS2017,我希望仍然没问题。如果你使用的是旧版本,你应该能够实现相同的方法略长一点。)