在与

时间:2016-05-27 11:39:02

标签: c# optimization

我在一个类中有一个数组:

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使用各种令人讨厌的技巧,如不安全或静态缓存代码。 不行将这些优化泄露给客户端代码。

1 个答案:

答案 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)来考虑实际问题。此外,这种方法还将创建一个私有后备字段,它将产生相同的内存占用。