如何降低GetHashCode的复杂性

本文关键字:复杂性 GetHashCode 何降低 | 更新日期: 2023-09-27 18:04:35

我想减少我的代码执行时间。查看一些测试结果,我发现GetHashCode()占用了21.62%的执行时间。

我也得到了一个警告:

警告1 DA0010: .*. gethashcode () = 7,63;GetHashCode方法函数应该是便宜的,不分配任何内存。降低哈希复杂度代码函数

代码片段:

My GetHashCode() in Field Class:

    public override int GetHashCode()
    {
        int hash = 7;
        hash = (hash * 13) + this.Coordinate.GetHashCode();
        return hash;
    }

My GetHashCode() in Coordinate Class:

    public override int GetHashCode()
    {
        int hash = 17;
        hash = (hash * 23) + this.Row.GetHashCode();
        hash = (hash * 23) + this.Column.GetHashCode();
        return hash;
    }

Edit: Row和Column只是字节变量。我只需要调用它们的属性在get访问器

中返回一个字节

My GetHashCode() in Sudoku Class:

    public override int GetHashCode()
    {
        int hash = 7;
        hash = (hash * 5) + this.Grid.GetHashCode();
        return hash;
    }

编辑:网格只是一个多维数组类型:Field[,],我只是调用它的属性这里返回一个字段[,]网格通过它的get访问器。

问题:我怎样才能大大降低我的GetHashCode()的复杂性和提高它的性能?为什么GetHashCode()方法的性能如此之低?

如何降低GetHashCode的复杂性

我想你会发现GetHashCode不是你的问题。如果你在GetHashCode中花费了超过20%的时间,你就必须进行大量的字典查找。或者你把哈希码用在了不该用的地方。

GetHashCode可能是性能问题的表现,但几乎可以肯定它不是原因。

您的计算只是添加一个内容到您的哈希码。只有组合你的哈希码需要一个更好的哈希码,而不是仅仅添加两个值:

//Field 
public override int GetHashCode()
{
    return this.Coordinate.GetHashCode();
}
//Coordinate 
public override int GetHashCode()
{
    return  this.Column.GetHashCode() * 17 + this.Row.GetHashCode();
}    
//Sudoku, I doubt if this is ever called...
public override int GetHashCode()
{
    return this.Grid.GetHashCode();
}

对于性能,它实际上取决于你调用GetHashCode的频率(如果你做任何计算)。或者如果您将它们存储在某种字典中,问题可能是具有相同散列的多个值,这将减少对字典/散列表中对象的访问时间。所以你的哈希函数必须是你要存储的集合的一个很好的分布。

如果您的类没有太多的变异体,您可以缓存哈希代码并只返回GetHashCode()的缓存值。(即使您有很多mutator,您也可以这样做,但如果对象经常发生突变,则效果可能会差得多。)

你应该懒惰地计算它。你需要知道什么时候它是脏的,需要重新计算。您可以通过添加bool isHashCodeDirty字段轻松地做到这一点,该字段在构造类时初始化为true,并且每个mutator方法都将其初始化为true。

然后在GetHashCode()的实现中,如果isHashCodeDirty为真,将其设置为假并重新计算并返回哈希码。如果为false,则返回缓存的值。

当然,在这里你必须小心使用多线程。我认为在GetHashCode()中添加锁会对性能产生很大的影响!

最理想的当然是拥有不可变的类;然后只需在构造函数中计算一次哈希码,此后它将永远不会更改。

看起来问题不在于整数加法,而在于访问这样的属性。坐标,这个。网格等

看一下它们的get访问器,它们可能做了一些额外的工作。