我在一个类中有一个数组:
class MatchNode
{
public short X;
public short Y;
public NodeVal[] ControlPoints;
private MatchNode()
{
ControlPoints = new NodeVal[4];
}
}
NodeVal
是:
struct NodeVal
{
public readonly short X;
public readonly short Y;
public NodeVal(short x, short y)
{
X = x;
Y = y;
}
}
现在,如果我们想将性能提升到新的水平并且避免为阵列提供单独的对象,该怎么办?实际上它不必有一个数组。唯一的限制是客户端代码应该能够通过索引访问NodeVal
,如:
matchNode.ControlPoints[i]
OR
matchNode[i]
当然,解决方案应该比数组访问更快或更快,因为它应该是一个优化。
编辑:正如Ryan所说,似乎我应该更多地解释一下这个动机:
MatchNode
类在项目中被大量使用。项目中使用了数百个,每个都被访问了数百次,因此尽可能简洁,简洁,可以减少缓存未命中和整体性能。
让我们考虑64位机器。在当前实现的类中,数组需要8个字节用于ControlPoints引用,并且数组对象的大小将至少 16个字节的对象开销(对于方法表和同步块)和16个字节用于实际的字节。因此,除了16字节的实际数据之外,我们至少有24个开销字节。
这些对象用于项目的瓶颈,所以如果我们可以更多地优化它们就很重要。
当然我们可以拥有一个超级大的NodeVal
数组,只需在MatchNode
中保存一个可以找到实际数据的索引,但它会再次改变使用{{1}的每个客户端代码s,更不用说是一个肮脏的非面向对象的解决方案。
好的有一个凌乱的MatchNode
使用各种令人讨厌的技巧,如不安全或静态缓存代码。 不行将这些优化泄露给客户端代码。
答案 0 :(得分:0)
你正在寻找indexers:
class MatchNode
{
public short X;
public short Y;
private NodeVal[] myField;
public NodeVal this[int i] { get { return myField[i]; } set { myField[i] = value; } }
public MatchNode(int size) { this.myField = new NodeVal[size]; }
}
现在你可以简单地使用它:
var m = new MatchNode(10);
m[0] = new NodeVal();
但是我怀疑这会以任何方式影响性能(至少在速度方面),你应该使用分析工具(例如dotTrace)来考虑实际问题。此外,这种方法还将创建一个私有后备字段,它将产生相同的内存占用。