Runtime: 提案System.HashCodeを远加しお、適切なハッシュコヌドを簡単に生成できるようにしたす。

䜜成日 2016幎12月09日  Â·  182コメント  Â·  ゜ヌス: dotnet/runtime

2017幎6月16日曎新ボランティアを探しおいたす

APIシェむプが完成したした。 ただし、実装に䜿甚する候補のリストから最適なハッシュアルゎリズムをただ決定しおいるため、各アルゎリズムのスルヌプット/分散を枬定するのを手䌝っおくれる人が必芁です。 その圹割を匕き受けたい堎合は、䞋にコメントを残しおください。 @ karelzがこの問題を割り圓おたす。

アップデヌト2017幎6月13日提案が受理されたした

ここで@terrajobstにより承認されたAPIですhttps://github.com/dotnet/corefx/issues/14354#issuecomment -308190321は

// Will live in the core assembly
// .NET Framework : mscorlib
// .NET Core      : System.Runtime / System.Private.CoreLib
namespace System
{
    public struct HashCode
    {
        public static int Combine<T1>(T1 value1);
        public static int Combine<T1, T2>(T1 value1, T2 value2);
        public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3);
        public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4);
        public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5);
        public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6);
        public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7);
        public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8);

        public void Add<T>(T value);
        public void Add<T>(T value, IEqualityComparer<T> comparer);

        [Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
        [EditorBrowsable(Never)]
        public override int GetHashCode();

        public int ToHashCode();
    }
}

この提案の原文は次のずおりです。

理論的根拠

優れたハッシュコヌドを生成するために、醜い魔法の定数を䜿甚したり、コヌドを少しいじったりする必芁はありたせん。 次のような悪いが簡朔なGetHashCode実装を曞くこずはそれほど魅力的ではないはずです。

class Person
{
    public override int GetHashCode() => FirstName.GetHashCode() + LastName.GetHashCode();
}

提案

HashCodeタむプを远加しお、ハッシュコヌドの䜜成をカプセル化し、開発者が厄介な詳现に混乱するのを回避する必芁がありたす。 これが私の提案です。これはhttps://github.com/dotnet/corefx/issues/14354#issuecomment-305019329に基づいおおり、いく぀かのマむナヌな改蚂が加えられおいたす。

// Will live in the core assembly
// .NET Framework : mscorlib
// .NET Core      : System.Runtime / System.Private.CoreLib
namespace System
{
    public struct HashCode
    {
        public static int Combine<T1>(T1 value1);
        public static int Combine<T1, T2>(T1 value1, T2 value2);
        public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3);
        public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4);
        public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5);
        public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6);
        public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7);
        public static int Combine<T1, T2, T3, T4, T5, T6, T7, T8>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8);

        public void Add<T>(T value);
        public void Add<T>(T value, IEqualityComparer<T> comparer);
        public void AddRange<T>(T[] values);
        public void AddRange<T>(T[] values, int index, int count);
        public void AddRange<T>(T[] values, int index, int count, IEqualityComparer<T> comparer);

        [Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
        public override int GetHashCode();

        public int ToHashCode();
    }
}

備考

コメント@terrajobstを参照しおくださいhttps://github.com/dotnet/corefx/issues/14354#issuecomment -305019329このAPIの目的のために、 圌の発蚀はすべお有効です。 ただし、特にこれらを指摘したいず思いたす。

  • APIは匷力な暗号化ハッシュを生成する
  • APIは「a」ハッシュコヌドを提䟛したすが、特定のハッシュコヌドアルゎリズムを保蚌するものではありたせん。 これにより、埌で別のアルゎリズムを䜿甚したり、別のアヌキテクチャで別のアルゎリズムを䜿甚したりできたす。
  • APIは、特定のプロセス内で同じ倀が同じハッシュコヌドを生成するこずを保蚌したす。 同じアプリの異なるむンスタンスは、ランダム化のために異なるハッシュコヌドを生成する可胜性がありたす。 これにより、コンシュヌマヌがハッシュ倀を氞続化できず、実行間たたはさらに悪いこずに、プラットフォヌムのバヌゞョンにわたっおハッシュ倀が安定しおいるこずに誀っお䟝存するこずがなくなりたす。
api-approved area-System.Numerics up-for-grabs

最も参考になるコメント

決定

  • シナリオが䞍明確なため、すべおのAddRangeメ゜ッドを削陀する必芁がありたす。 配列が頻繁に衚瀺される可胜性はほずんどありたせん。 そしお、より倧きな配列が含たれるず、問題は蚈算をキャッシュする必芁があるかどうかです。 呌び出し偎でforルヌプを芋るず、それに぀いお考える必芁があるこずが明らかになりたす。
  • たた、 IEnumerableオヌバヌロヌドをAddRangeに远加したくないの
  • stringずStringComparisonを必芁ずするAddぞのオヌバヌロヌドは必芁ないず思いたす。 はい、 IEqualityComparerを介しお呌び出すよりも効率的である可胜性がありたすが、埌で修正できたす。
  • GetHashCodeを゚ラヌで廃止されたものずしおマヌクするのは良い考えですが、さらに䞀歩進んでIntelliSenseから隠したす。

これにより、次のこずが可胜になりたす。

`` `C
//コアアセンブリに存圚したす
// .NET Frameworkmscorlib
// .NET CoreSystem.Runtime / System.Private.CoreLib
名前空間システム
{{
public struct HashCode
{{
public static int CombineT1倀1;
public static int CombineT1倀1、T2倀2;
public static int CombineT1倀1、T2倀2、T3倀3;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6、T7倀7;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6、T7倀7、T8倀8;

    public void Add<T>(T value);
    public void Add<T>(T value, IEqualityComparer<T> comparer);

    [Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
    [EditorBrowsable(Never)]
    public override int GetHashCode();

    public int ToHashCode();
}

}
`` `

党おのコメント182件

提案ハッシュランダム化サポヌトを远加

public static HashCode Randomized<T> { get; } // or CreateRandomized<T>
or 
public static HashCode Randomized(Type type); // or CreateRandomized(Type type)

同じタむプの同じランダム化ハッシュを取埗するには、 TたたはType typeが必芁です。

提案コレクションのサポヌトを远加する

public HashCode Combine<T>(T[] values);
public HashCode Combine<T>(T[] values, IEqualityComparer<T> comparer);
public HashCode Combine<T>(Span<T> values);
public HashCode Combine<T>(Span<T> values, IEqualityComparer<T> comparer);
public HashCode Combine<T>(IEnumerable<T> values);
public HashCode Combine<T>(IEnumerable<T> IEqualityComparer<T> comparer);

次のコヌドHashCode.Empty.Combine(_field1).Combine(_field2).Combine(_field3).Combine(_field4).Combine(_field5);は、Combine呌び出しなしでむンラむン最適化する必芁があるため、オヌバヌロヌドCombine(_field1, _field2, _field3, _field4, _field5)は必芁ないず思いたす。

@AlexRadch

提案コレクションのサポヌトを远加する

はい、それはこの提案の最終的な蚈画の䞀郚でした。 ただし、これらのメ゜ッドを远加する前に、APIがどのように衚瀺されるかに焊点を圓おるこずが重芁だず思いたす。

圌は、coreclrの文字列に䜿甚されるMarvin32ハッシュなど、別のアルゎリズムを䜿甚したいず考えおいたした。 これには、HashCodeのサむズを8バむトに拡匵する必芁がありたす。

4バむトたたは8バむト盞圓のデヌタを内郚に栌玍するHash32およびHash64タむプがあるのはどうですか それぞれの長所/短所を文曞化したす。 Hash64はXには適しおいたすが、速床が䜎䞋する可胜性がありたす。 Hash32の方が高速ですが、分散されおいない可胜性がありたすたたは実際のトレヌドオフは䜕でも。

圌はハッシュシヌドをランダム化したかったので、ハッシュは決定論的ではありたせんでした。

これは䟿利な動䜜のようです。 しかし、私はこれを制埡したい人々を芋るこずができたした。 したがっお、ハッシュを䜜成するには2぀の方法が必芁です。1぀はシヌドを取埗しないそしおランダムシヌドを䜿甚する方法で、もう1぀はシヌドを提䟛できるようにする方法です。

泚Roslynは、これがFxで提䟛されるこずを望んでいたす。 ナヌザヌにGetHashCodeを吐き出す機胜を远加しおいたす。 珟圚、次のようなコヌドを生成したす。

c# public override int GetHashCode() { var hashCode = -1923861349; hashCode = hashCode * -1521134295 + this.b.GetHashCode(); hashCode = hashCode * -1521134295 + this.i.GetHashCode(); hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(this.s); return hashCode; }

これは玠晎らしい経隓ではなく、倚くの醜い抂念を明らかにしたす。 代わりに呌び出すこずができるHash.WhateverAPIがあるずワクワクしたす。

ありがずう

MurmurHashはどうですか 適床に高速で、非垞に優れたハッシュ特性を備えおいたす。 たた、2぀の異なる実装がありたす。1぀は32ビットハッシュを吐き出すもので、もう1぀は128ビットハッシュを吐き出すものです。

32ビット圢匏ず128ビット圢匏の䞡方のベクトル化された実装もありたす。

@tannergooding MurmurHashは高速ですが、このブログ投皿の音からするず安党ではありたせん。

@jkotas 、昚幎の議論以来、32ビットで4バむトを超える構造䜓に察しおより良いコヌドを生成するこずに関しおJITで䜕か䜜業がありたしたか たた、 @ CyrusNajmabadiの提案に぀いおどう思いたすか

4バむトたたは8バむト盞圓のデヌタを内郚に栌玍するHash32およびHash64タむプがあるのはどうですか それぞれの長所/短所を文曞化したす。 Hash64はXには適しおいたすが、速床が䜎䞋する可胜性がありたす。 Hash32の方が高速ですが、分散されおいない可胜性がありたすたたは実際のトレヌドオフは䜕でも。

私はただこのタむプが開発者に提䟛するのに非垞に䟡倀があるず思いたす、そしおそれが2.0でそれを持っおいるこずは玠晎らしいでしょう。

@jamesqo 、この実装は暗号的に安党である必芁はないず思いたすこれが、明瀺的な暗号ハッシュ関数の目的です。

たた、その蚘事はMurmur2にも適甚されたす。 この問題は、Murmur3アルゎリズムで解決されたした。

昚幎の議論以来、32ビットで4バむトを超える構造䜓に察しおより良いコヌドを生成するこずに関するJIT

私は䜕も知りたせん。

@CyrusNajmabadiの提案に぀いおどう思いたすか

フレヌムワヌクタむプは、95以䞊のケヌスでうたく機胜する単玔な遞択である必芁がありたす。 それらは最速のものではないかもしれたせんが、それは問題ありたせん。 Hash32ずHash64のどちらかを遞択するのは簡単な遞択ではありたせん。

それは私にずっおは倧䞈倫です。 しかし、少なくずもこれらの95のケヌスに察しお十分な解決策を埗るこずができたすか 今は䜕もありたせん...-/

hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCodethis.s;

@CyrusNajmabadiなぜthis.s.GetHashCodeだけでなく、ここでEqualityComparerを呌び出しおいるのですか

非構造䜓の堎合nullをチェックする必芁がないようにしたす。

これは、舞台裏でも匿名型に察しお生成するものに近いものです。 既知のnull以倖の倀の堎合を最適化しお、ナヌザヌにずっおより快適なコヌドを生成したす。 ただし、このためのAPIが組み蟌たれおいるず䟿利です。

EqualityComparer.Default.GetHashCodeの呌び出しは、nullをチェックするよりも10倍以䞊高䟡です。

EqualityComparer.Default.GetHashCodeの呌び出しは、nullをチェックするよりも10倍以䞊コストがかかりたす。

問題のように聞こえたす。 良いハッシュコヌドAPIがあれば、Fxで呌び出すこずができたす:)

たた、匿名型でもその問題が発生したす。これは、そこで生成されるものでもあるためです。

タプルに察しお䜕をするかはわかりたせんが、䌌おいるず思いたす。

タプルに察しお䜕をするかはわかりたせんが、䌌おいるず思いたす。

System.Tupleは、歎史的な理由でEqualityComparer<Object>.Defaultを通過したす。 System.ValueTupleは、nullチェックを䜿甚しおObject.GetHashCodeを呌び出したす-https //github.com/dotnet/coreclr/blob/master/src/mscorlib/shared/System/ValueTuple.cs#L809。

倧野。 タプルは「HashHelpers」を䜿甚できるようです。 ナヌザヌが同じ利益を埗るこずができるように、それを公開するこずはできたすか

玠晎らしい。 私は同じようなこずをしおうれしいです。 匿名タむプから始めたのは、それらが劥圓なベストプラクティスであるず考えたためです。 そうでない堎合は、それで問題ありたせん。 :)

しかし、それは私がここにいる理由ではありたせん。 私は実際にハッシュを効果的に組み合わせるシステムを手に入れるためにここにいたす。 それが提䟛できる堎合は、乱数をハヌドコヌディングしおハッシュ倀を自分で組み合わせるのではなく、喜んでその呌び出しに移りたす。

コンパむラヌが生成したコヌドに最適だず思うAPIの圢は䜕でしょうか

文字通り、以前に提瀺された32ビット゜リュヌションのいずれも私には問題ありたせん。 ちなみに、64ビット゜リュヌションは私には問題ありたせん。 「ハッシュをある皮の合理的な方法で組み合わせお、合理的に分散された結果を生成できる」ずいう、取埗できるAPIの䞀皮です。

私はこれらのステヌトメントを調敎するこずはできたせん

サむズが4バむトの䞍倉のHashCode構造䜓がありたした。 提䟛されたハッシュコヌドをDJBX33Xのようなアルゎリズムを介しお独自のハッシュコヌドず混合し、新しいHashCodeを返すCombineintメ゜ッドがありたした。

@jkotasは、DJBX33Xのようなアルゎリズムが十分に堅牢であるずは考えおいたせんでした。

ず

フレヌムワヌクタむプは、95以䞊のケヌスでうたく機胜する単玔な遞択である必芁がありたす。

95のケヌスで十分に機胜する単玔な32ビットの环積ハッシュを思い付くこずができたせんか ここでうたく凊理されおいないケヌスは䜕ですか、そしおなぜそれらが95のケヌスにあるず思いたすか

@jkotas 、パフォヌマンスはこのタむプにずっお本圓に重芁ですか 平均しお、ハッシュテヌブルルックアップのようなものであり、これはいく぀かの構造䜓コピヌよりもはるかに時間がかかるず思いたす。 ボトルネックであるこずが刀明した堎合は、APIのリリヌス埌に32ビットの構造䜓コピヌを最適化するようJITチヌムに䟝頌しお、最適化に取り組んでいる人がいないずきにこのAPIをブロックするのではなく、䜕らかのむンセンティブを埗るのが劥圓でしょうか。コピヌ

95のケヌスで十分に機胜する単玔な32ビットの环積ハッシュを思い付くこずができたせんか

デフォルトでは、文字列の32ビット环積ハッシュが非垞にひどく焌かれおいたす。そのため、.NETCoreの文字列のMarvinハッシュ-https//github.com/dotnet/corert/blob/87e58839d6629b5f90777f886a2f52d7a99c076f/src/System.Private.CoreLib/ src / System / Marvin.csL25。 ここで同じ過ちを繰り返したくないず思いたす。

@jkotas 、パフォヌマンスはこのタむプにずっお本圓に重芁ですか

パフォヌマンスは重芁ではないず思いたす。 このAPIは自動生成されたコンパむラコヌドで䜿甚されるように芋えるので、芋た目よりも小さい生成コヌドを優先する必芁があるず思いたす。 非流暢なパタヌンはより小さなコヌドです。

文字列のハッシュを环積するデフォルトの32ビットは本圓にひどく焌かれおいたす

それは95の堎合のようには思えたせん。 私たちは通垞の開発者が、今日手動で物事を行うすべおのタむプに「十分に良い」ハッシュを望んでいるこずに぀いお話しおいる。

このAPIは自動生成されたコンパむラコヌドで䜿甚されるように芋えるので、芋た目よりも小さい生成コヌドを優先する必芁があるず思いたす。 非流暢なパタヌンはより小さなコヌドです。

これはRoslynコンパむラでは䜿甚できたせん。 これは、ナヌザヌがタむプのGetHashCodesを生成するのを支揎するずきにRoslynIDEが䜿甚するためのものです。 これは、ナヌザヌが衚瀺しお維持する必芁のあるコヌドであり、次のような賢明なものがありたす。

`` `c
Hash.Combinethis.A.GetHashCode?? 0、
this.B.GetHashCode?? 0、
this.C.GetHashCode?? 0;

is a lot nicer than a user seeing and having to maintain:

```c#
            var hashCode = -1923861349;
            hashCode = hashCode * -1521134295 + this.b.GetHashCode();
            hashCode = hashCode * -1521134295 + this.i.GetHashCode();
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(this.s);
            return hashCode;

぀たり、Fxにはすでにこのコヌドがありたす。

https://github.com/dotnet/roslyn/blob/master/src/Compilers/Test/Resources/Core/NetFX/ValueTuple/ValueTuple.cs#L5

タプルには十分だず思いたす。 自分のタむプで利甚できるようにするこずがなぜそんなに問題になるのか、私にはわかりたせん。

泚これをroslynで行うこずも怜蚎したした。

c# return (this.A, this.B, this.C).GetHashCode();

しかし今、あなたは人々に、ある皮の合理的なデフォルトのハッシュ動䜜を埗るためだけに朜圚的に倧きな構造䜓を生成するように匷制しおいたす。

私たちは通垞の開発者が、今日手動で物事を行うすべおのタむプに「十分に良い」ハッシュを望んでいるこずに぀いお話しおいる。

元の文字列ハッシュは、通垞の開発者にずっおうたく機胜する「十分に良い」ハッシュでした。 しかし、ASP.NET Webサヌバヌは、受信したものをハッシュテヌブルに保存する傟向があるため、DoS攻撃に察しお脆匱であるこずが発芋されたした。 したがっお、「十分に良い」ハッシュは基本的に悪いセキュリティ問題になりたした。

タプルには十分だず思いたす

必ずしもそうずは限りたせん。 タプルのバックストップ枬定を行い、ハッシュコヌドをランダム化しお、埌でアルゎリズムを倉曎するオプションを提䟛したした。

     return Hash.Combine(this.A?.GetHashCode() ?? 0,
                         this.B?.GetHashCode() ?? 0,
                         this.C?.GetHashCode() ?? 0);

これは私には合理的に芋えたす。

私はあなたのポゞトむンを取埗したせん。 あなたは2぀のこずを蚀っおいるようです

元の文字列ハッシュは、通垞の開発者にずっおうたく機胜する「十分に良い」ハッシュでした。 しかし、ASP.NET Webサヌバヌは、受信したものをハッシュテヌブルに保存する傟向があるため、DoS攻撃に察しお脆匱であるこずが発芋されたした。 したがっお、「十分に良い」ハッシュは基本的に悪いセキュリティ問題になりたした。

その堎合は、セキュリティやDoSに懞念がある人に適したハッシュコヌドを提䟛したしょう。

フレヌムワヌクタむプは、95以䞊のケヌスでうたく機胜する単玔な遞択である必芁がありたす。

その堎合は、95のケヌスに十分なハッシュコヌドを提䟛したしょう。 セキュリティ/ DoSに懞念がある人は、その目的のために文曞化された専甚のフォヌムを䜿甚できたす。

必ずしもそうずは限りたせん。 タプルのバックストップ枬定を行い、ハッシュコヌドをランダム化しお、埌でアルゎリズムを倉曎するオプションを提䟛したした。

Ok。 ナヌザヌが同じメカニズムを䜿甚できるように、それを公開できたすか

-
「普遍的な解決策を䜜るこずができないので、誰もが自分で解決しなければならない」ず蚀っおいるように聞こえるので、私はここで本圓に苊劎しおいたす。 これは、最悪の堎所の1぀に思えたす。確かに、ほずんどのお客様は、DoSの懞念のために独自の「マヌビンハッシュ」を䜜成するこずを考えおいないためです。 それらは、フィヌルドハッシュを1぀の最終ハッシュに远加、排他的論理和、たたはその他の方法でうたく組み合わせおいないだけです。

95のケヌスを気にする堎合は、䞀般的に優れたenoghハッシュを䜜成する必芁がありたす。 5のケヌスを気にする堎合は、そのための特別な゜リュヌションを提䟛できたす。

これは私には合理的に芋えたす。

すばらしい:)次に公開できたすか

`` `c
名前空間System.Numerics.Hashing
{{
内郚静的クラスHashHelpers
{{
public static readonly int RandomSeed = new Random。NextInt32.MinValue、Int32.MaxValue;

    public static int Combine(int h1, int h2)
    {
        // RyuJIT optimizes this to use the ROL instruction
        // Related GitHub pull request: dotnet/coreclr#1830
        uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
        return ((int)rol5 + h1) ^ h2;
    }
}
Roslyn could then generate:

```c#
     return Hash.Combine(Hash.RandomSeed,
                         this.A?.GetHashCode() ?? 0,
                         this.B?.GetHashCode() ?? 0,
                         this.C?.GetHashCode() ?? 0);

これには、ほずんどの堎合に実際に「十分に良い」ずいう利点がありたすが、ランダムでないハッシュに䟝存しないように、ランダムな倀で初期化するずいう良い道を人々に導きたす。

セキュリティ/ DoSに懞念がある人は、その目的のために文曞化された専甚のフォヌムを䜿甚できたす。

すべおのASP.NETアプリには、セキュリティ/ DoSの懞念がありたす。

すばらしい:)次に公開できたすか

これは私が合理的だず蚀ったこずずは異なりたす。

https://github.com/aspnet/Common/blob/dev/shared/Microsoft.Extensions.HashCodeCombiner.Sources/HashCodeCombiner.csに぀いおどう思いたすか。 これは、ASP.NETの内郚で今日倚くの堎所で䜿甚されおいるものであり、私が非垞に満足しおいるものですただし、結合関数をより匷力にする必芁がありたす。実装の詳现を調敎し続けるこずができたす。

@jkotas聞いたよp

したがっお、ここでの問題は、開発者がDoS攻撃の圱響を受けやすい時期がわからないこずです。これは、開発者がそれに぀いお䜕も考えおいないためです。そのため、Marvin32を䜿甚するように文字列を切り替えたした。

それを蚌明する方法がないので、「95のケヌスは問題ではない」ずいう道を進むべきではありたせん。パフォヌマンスコストがあっおも、泚意を怠る必芁がありたす。 それから離れる堎合は、ハッシュコヌドの実装には、「これで十分だ」ず刀断するだけでなく、暗号化ボヌドのレビュヌが必芁です。

すべおのASP.NETアプリには、セキュリティ/ DoSの懞念がありたす。

Ok。 では、今日、誰もハッシュコヌドの助けを借りおいないため、うたく機胜しおいない可胜性があるずいう問題にどのように察凊しおいたすか 明らかに、そのような䞖界の状態を持぀こずは容認されおいたす。 では、今日人々が手で転がしおいるものよりもパフォヌマンスが優れおいるず思われる合理的なハッシュシステムを提䟛するこずによっお䜕が害されるのでしょうか。

それを蚌明する方法がないので、パフォヌマンスが犠牲になったずしおも、泚意を怠らなければなりたせん。

あなたが䜕かを提䟛しなければ、人々はただひどいこずをし続けるでしょう。 完璧なものが䜕もないずいう理由で「十分に良い」を拒吊するこずは、今日の珟状が悪いこずを意味したす。

すべおのASP.NETアプリには、セキュリティ/ DoSの懞念がありたす。

これを説明できたすか 私が理解しおいるように、任意の入力を受け入れお、入力を特別に现工できる堎合はパフォヌマンスが䜎䞋するデヌタ構造にそれを栌玍する堎合、DoSの懞念がありたす。 わかりたした、それがナヌザヌから来たWebシナリオで取埗する文字列に関する懞念事項であるこずがわかりたした。

では、このシナリオで䜿甚されおいない残りのタむプにどのように適甚されるのでしょうか。

次のタむプのセットがありたす。

  1. DoSセヌフである必芁があるナヌザヌタむプ。 珟圚、私たちは支揎するものを䜕も提䟛しおいたせん。そのため、人々が正しいこずをしおいない可胜性が高いため、私たちはすでに悪い堎所にいたす。
  2. DoSセヌフである必芁のないナヌザヌタむプ。 珟圚、私たちは支揎するものを䜕も提䟛しおいたせん。そのため、人々が正しいこずをしおいない可胜性が高いため、私たちはすでに悪い堎所にいたす。
  3. DoSセヌフである必芁があるフレヌムワヌクタむプ。 珟圚、それらをDoSセヌフにしおいたすが、APIを介しお公開しおいたせん。
  4. DoSセヌフである必芁のないフレヌムワヌクのタむプミス。 珟圚、ハッシュを提䟛しおいたすが、APIを介しお公開しおいたせん。

基本的に、これらのケヌスは重芁であるず考えおいたすが、「1」たたは「2」を凊理する゜リュヌションをナヌザヌに実際に提䟛するには十分ではありたせん。 「2」の解決策が「1」に適さないのではないかず心配しおいるので、そもそもそれを提䟛するこずすらしたせん。 そしお、「1」の解決策を提䟛する気さえなければ、私たちは信じられないほど奇劙な立堎にいるように感じたす。 私たちはDoSingずASPに぀いお心配しおいたすが、実際に人々を助けるために心配しおいたせん。 そしお、私たちはそれで人々を助けないので、DoS以倖のケヌスでそれを助ける぀もりさえありたせん。

-

これらの2぀のケヌスが重芁である堎合私はそれを受け入れおも構わないず思っおいたす、2぀のAPIを提䟛しないのはなぜですか それらを文曞化したす。 圌らが䜕のためにあるのかを明確にしおください。 人々がそれらを適切に䜿甚するならば、玠晎らしい。 人々がそれらを適切に䜿甚しなくおも、それでも問題ありたせん。 結局のずころ、圌らはずにかく今日は物事を適切に行っおいない可胜性が高いので、物事はどのように悪化しおいたすか

に぀いおどう思いたすか

私はどちらの方法でも意芋がありたせん。 顧客が䜿甚できるAPIであり、蚱容できるパフォヌマンスを発揮し、明確なコヌドを備えたシンプルなAPIを提䟛するのであれば、それで問題ないず思いたす。

フィヌルド/プロパティのセットを順序付けられた方法で結合したいずいう99のケヌスを凊理する、単玔な静的フォヌムがあるず䟿利だず思いたす。 そのようなものをこのタむプにかなり簡単に远加できるようです。

シンプルな静的な圢があればいいず思いたす

同意。

フィヌルド/プロパティのセットを順序付けられた方法で結合したいずいう99のケヌスを凊理する、単玔な静的フォヌムがあるず䟿利だず思いたす。 そのようなものをこのタむプにかなり簡単に远加できるようです。

同意。

ある皮のAPIが実珟するのを本圓に芋たいので、これに぀いおは途䞭でお䌚いしたしょう。 @jkotas䞍倉のむンスタンスベヌスのAPIを远加するこずに反察しおいるこずを私はただ理解しおいたせん。 最初に、32ビットコピヌが遅いためだず蚀いたした。次に、可倉APIがより簡朔になるためですこれは正しくありたせん。 h.Combine(a).Combine(b) 䞍倉バヌゞョンはh.Combine(a); h.Combine(b); 可倉バヌゞョンよりも短いですバヌゞョン。

そうは蚀っおも、私は戻っお喜んで

public static class HashCode
{
    public static int Combine<T>(T value1, Tvalue2);
    public static int Combine<T>(T value1, Tvalue2, IEqualityComparer<T> comparer);
    public static int Combine<T>(T value1, Tvalue2, T value3);
    public static int Combine<T>(T value1, Tvalue2, T value3, IEqualityComparer<T> comparer);
    public static int Combine<T>(T value1, Tvalue2, T value3, T value4);
    public static int Combine<T>(T value1, Tvalue2, T value3, T value4, IEqualityComparer<T> comparer);
    // ... All the way until value8
}

これは合理的だず思いたすか

珟圚、投皿を線集するこずはできたせんが、すべおのメ゜ッドがTを受け入れるこずができるわけではないこずに気付きたした。その堎合、すべおのintを受け入れる8぀のオヌバヌロヌドがあり、ナヌザヌにGetHashCodeを呌び出させるこずができたす。

これらの2぀のケヌスが重芁である堎合私はそれを受け入れおも構わないず思っおいたす、2぀のAPIを提䟛しないのはなぜですか それらを文曞化したす。 圌らが䜕のためにあるのかを明確にしおください。 人々がそれらを適切に䜿甚すれば、玠晎らしい。 人々がそれらを適切に䜿甚しなくおも、それでも問題ありたせん。 結局のずころ、圌らはずにかく今日は物事を適切に行っおいない可胜性が高いので、状況はどのように悪化しおいたすか

圌らがそこにいるずき、人々は物事を適切に䜿甚しないからです。 簡単な䟋、XSSを芋おみたしょう。 最初から、Webフォヌムでさえ出力をHTML゚ンコヌドする機胜がありたした。 ただし、開発者はリスクを知らず、適切に行う方法も知らず、手遅れになったずきにのみアプリが公開され、認蚌Cookieが解陀されたした。

人々にセキュリティの遞択を䞎えるこずは、圌らが圌らを前提ずしおいたす

  1. 問題に぀いお知っおください。
  2. リスクが䜕であるかを理解したす。
  3. それらのリスクを評䟡できたす。
  4. 正しいこずを簡単に芋぀けるこずができたす。

これらの仮定は、䞀般的に倧倚数の開発者には圓おはたりたせん。圌らは、手遅れになったずきにのみ問題を芋぀けたす。 開発者はセキュリティ䌚議に参加せず、ホワむトペヌパヌを読んだり、゜リュヌションを理解したりしたせん。 そのため、ASP.NET HashDoSシナリオでは、それらを遞択したした。これは正しいこずであり、最倧の圱響を䞎えたため、デフォルトで保護したした。 しかし、それを文字列にのみ適甚したため、ナヌザヌ入力からカスタムクラスを構築しおいた人々は悪い堎所に眮かれたした。 私たちは正しいこずをし、今すぐそれらの顧客を保護し、それをデフォルトにしお、倱敗ではなく成功の萜ずし穎を持たせる必芁がありたす。 セキュリティのためのAPI蚭蚈は、遞択ではなく、ナヌザヌがそれを知っおいるかどうかに関係なく支揎するこずを目的ずしおいる堎合がありたす。

ナヌザヌはい぀でもセキュリティに焊点を圓おおいないハッシュを䜜成できたす。 したがっお、2぀のオプションが䞎えられたす

  1. デフォルトのハッシュナヌティリティはセキュリティに察応しおいたせん。 ナヌザヌはセキュリティを意識したハッシュ関数を䜜成できたす
  2. デフォルトのハッシュナヌティリティはセキュリティに察応しおいたす。 ナヌザヌは、セキュリティを意識しないカスタムハッシュ関数を䜜成できたす

次に、2番目の方がおそらく優れおいたす。 そしお、提案されおいるこずは、暗号化ハッシュに察するフルのパフォヌマンスぞの圱響はありたせん。 だからそれは良い劥協点になりたすか

これらのスレッドで実行されおいる質問の1぀は、どのアルゎリズムがすべおの人に最適かずいうこずです。 完璧なアルゎリズムは1぀もないず蚀っおも過蚀ではありたせん。 ただし、 @ CyrusNajmabadiが瀺しおいるような、䞀般的な.NET入力の゚ントロピヌが䞍十分な傟向があるコヌドやその他の䞀般的なハッシャヌバグ入力デヌタの損倱や簡単なものなどよりも優れたコヌドを提䟛するこずを

「最良のアルゎリズム」の問題を回避するためのいく぀かのオプションを提案したいず思いたす。

  1. 明瀺的な遞択暗号化されおいないハッシュのスむヌトたずえば、xxHash、Marvin32、およびSpookyHashのAPI提案をすぐに送信するこずを蚈画しおいたす。 このようなAPIの䜿甚法は、HashCodeたたはHashCodeHelperタむプずは少し異なりたすが、説明のために、これらの違いを解決できるず仮定したす。 GetHashCodeにそのAPIを䜿甚する堎合

    • 生成されたコヌドは、それが䜕をしおいるのかを明瀺しおいたす。RoslynがMarvin32.Create();生成するず、パワヌナヌザヌはそれが䜕をするこずに決めたかを知るこずができ、必芁に応じおスむヌト内の別のアルゎリズムに簡単に倉曎できたす。

    • これは、倉曎を壊すこずを心配する必芁がないこずを意味したす。 非ランダム化/䞍十分な゚ントロピヌ/遅いアルゎリズムから始める堎合は、Roslynを曎新するだけで、新しいコヌドで他の䜕かを生成し始めるこずができたす。 叀いコヌドは叀いハッシュを䜿甚し続け、新しいコヌドは新しいハッシュを䜿甚したす。 開発者たたはRoslynコヌド修正は、必芁に応じお叀いコヌドを倉曎できたす。

    • 私が考えるこずができる最倧の欠点は、GetHashCodeに必芁な最適化のいく぀かが、他のアルゎリズムに悪圱響を䞎える可胜性があるこずです。 たずえば、32ビットの内郚状態は䞍倉の構造䜓でうたく機胜したすが、たずえばCityHashの256ビットの内郚状態はコピヌに倚くの時間を浪費する可胜性がありたす。

  1. ランダム化適切にランダム化されたアルゎリズムから始めたすランダムな初期倀で瀺されたコヌド@CyrusNajmabadiは、ランダム性を掗い流す可胜性があるため、カりントされたせん。 これにより、互換性の問題なしに実装を倉曎できるようになりたす。 アルゎリズムを倉曎する堎合でも、パフォヌマンスの倉曎に非垞に泚意を払う必芁がありたす。 ただし、アヌキテクチャごずたたはデバむスごずに遞択できるため、これも朜圚的なメリットになりたす。 たずえば、このサむトは、xxHashがx64 Macで最速であるのに察し、SpookyHashはXboxずiPhoneで最速であるこずを瀺しおいたす。 ある時点でアルゎリズムを倉曎する目的でこのルヌトをたどる堎合、64ビット以䞊の内郚状態が存圚する堎合でも劥圓なパフォヌマンスを維持するAPIの蚭蚈を怜蚎する必芁があるかもしれたせん。

CC @ bartonjs 、 @ terrajobst

@morganbr完璧なアルゎリズムは1に加えお、高床な䜿甚のための䞀連のアルゎリズムDictionary入れるために、マヌノィンが誰であるかを知る必芁はありたせん。

オブゞェクトを蟞曞に入れるために、マヌノィンが誰であるかを知る必芁はありたせん。

私はあなたがそれを眮く方法が奜きです。 私はあなたが蟞曞自䜓に぀いお蚀及したこずも奜きです。 IDictionaryは、あらゆる皮類の異なる品質を持぀倚数の異なるimplを持぀こずができるものです倚くのプラットフォヌムのコレクションAPIを参照しおください。 ただし、すべおのカテゎリで優れおいるずは限りたせんが、党䜓的にたずもな仕事をするベヌスの「蟞曞」を提䟛するだけです。

私はそれが人々のトンは、ハッシュラむブラリで探しおいるものだず思いたす。 たずえそれがすべおの目的に完璧でなくおも、仕事を成し遂げる䜕か。

@morganbr人々は単玔に、今日行っおいるこずよりも優れたGetHashCodeを䜜成する方法を望んでいるず思いたす通垞、Web䞊の䜕かからコピヌした数孊挔算のいく぀かのグラブバッグの組み合わせ。 うたく機胜する基本的な実装を提䟛できれば、人々は幞せになりたす。 特定のハッシュ関数が匷く必芁な堎合は、䞊玚ナヌザヌ向けの舞台裏APIを䜿甚できたす。

蚀い換えれば、今日ハッシュコヌドを曞いおいる人々は、なぜ圌らが䞍気味な察マヌノィン察぀ぶやきを欲するのかを知りも気にもしないでしょう。 それらの特定のハッシュコヌドの1぀を特に必芁ずしおいる人だけが探しに行きたす。 しかし、倚くの人は「これが私のオブゞェクトの状態です。蟞曞で䜿甚できる高速な分散ハッシュを生成する方法を提䟛しおくれたす。これにより、発生した堎合にDOSが実行されなくなるず思いたす。信頌できない入力を取埗しおハッシュし、保存したす。」

@CyrusNajmabadi問題は、珟圚の互換性の抂念を将来に拡匵するず、このタむプが出荷されるず倉曎できないこずがわかるこずですアルゎリズムが「すべおのアプリケヌションを攻撃可胜にする」方法でひどく壊れおいるこずがわかった堎合を陀く 。

ずにかく実行ごずに倀に䟝存するこずができなかったので、それが安定したランダム化された方法ずしお開始された堎合、実装を倉曎するのが簡単になるず䞀床䞻匵するこずができたす。 しかし、数幎埌、ハッシュバケットず䞀般的なケヌスのパフォヌマンスのバランスをずるのに、リストを含む構造を䜜成するアルゎリズムがあるこずがわかりたした。

モヌガンの提案では、今日䜜成するコヌドは、事実䞊、氞久に同じパフォヌマンス特性を持぀こずになりたす。 良くなったかもしれないアプリケヌションにずっお、これは残念なこずです。 悪化したであろうアプリケヌションにずっお、これは玠晎らしいこずです。 しかし、新しいアルゎリズムが芋぀かったら、それをチェックむンし、Roslynを倉曎しおそしおReSharperなどぞの倉曎を提案しお​​、SomeThingThatWasConsideredAwesomeIn2018ではなくNewAwesomeThing2019で生成を開始したす。

このようなスヌパヌブラックボックスは、䞀床しか実行できたせん。 そしお、私たちは氞遠にそれに固執しおいたす。 次に、誰かが次の実装を䜜成したす。これは平均パフォヌマンスが優れおいるため、2぀のブラックボックスの実装があり、どちらを遞択するのかわかりたせん。 そしお...そしお....

したがっお、確かに、Roslyn / ReSharper / etcがMarvin32、Murmur、FastHash、たたはIntPtr.Sizeに基づく組み合わせ/条件付きを䜿甚しおGetHashCodeを自動曞き蟌みした理由がわからない堎合がありたす。 しかし、あなたにはそれを調べる力がありたす。 そしお、新しい情報が明らかになったずきに、埌でタむプを倉曎する暩限がありたす...しかし、同じたたにする暩限も䞎えられおいたす。 これを曞くず悲しいでしょう。3幎埌、Roslyn / ReSharper / etcは、新しいアルゎリズムの方がはるかに優れおいるため、明瀺的に呌び出すこずを避けおいたす...通垞。

@bartonjs .Netがブラックボックスアルゎリズムたたはデヌタ構造を提䟛するすべおの堎所ずハッシュが異なる点は䜕ですか たずえば、䞊べ替えむントロ゜ヌト、 Dictionary 配列ベヌスの個別のチェヌン、 StringBuilder 8kチャンクのリンクリスト、ほずんどのLINQ。

今日はこれを詳しく芋おきたした。 この問題に関する遅延ず前埌の謝眪。

芁件

  • APIは誰のためのものですか

    • APIは匷力な暗号化ハッシュを生成する

    • ただし、APIは、フレヌムワヌク自䜓BCLやASP.NETなどで䜿甚できるように十分に優れおいる必芁がありたす。

    • ただし、これは、どこでもAPIを䜿甚する必芁があるずいう意味ではありたせん。 FXの䞀郚で、セキュリティ/ DOSのリスクのため、たたはパフォヌマンスのためにカスタムのものを䜿甚したい堎合は問題ありたせん。 䟋倖は垞に存圚したす。

  • このハッシュの望たしいプロパティは䜕ですか

    • 入力のすべおのビットが䜿甚されたす

    • 結果はよく分散されたす

    • APIは「a」ハッシュコヌドを提䟛したすが、特定のハッシュコヌドアルゎリズムを保蚌するものではありたせん。 これにより、埌で別のアルゎリズムを䜿甚したり、別のアヌキテクチャで別のアルゎリズムを䜿甚したりできたす。

    • APIは、特定のプロセス内で同じ倀が同じハッシュコヌドを生成するこずを保蚌したす。 同じアプリの異なるむンスタンスは、ランダム化のために異なるハッシュコヌドを生成する可胜性がありたす。 これにより、コンシュヌマヌがハッシュ倀を氞続化できず、実行間たたはさらに悪いこずに、プラットフォヌムのバヌゞョンにわたっおハッシュ倀が安定しおいるこずに誀っお䟝存するこずがなくなりたす。

APIシェむプ

`` `C
//コアアセンブリに存圚したす
// .NET Frameworkmscorlib
// .NET CoreSystem.Runtime / System.Private.CoreLib
名前空間システム
{{
public struct HashCode
{{
public static int CombineT1倀1;
public static int CombineT1倀1、T2倀2;
public static int CombineT1倀1、T2倀2、T3倀3;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6、T7倀7;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6、T7倀7、T8倀8;

    public void Add<T>(T value);
    public void Add<T>(T value, IEqualityComparer<T> comparer);
    public void Add<T>(T[] value);
    public void Add<T>(T[] value, int index, int length);
    public void Add(byte[] value);
    public void Add(byte[] value, int index, int length);
    public void Add(string value);
    public void Add(string value, StringComparison comparisonType);

    public int ToHashCode();
}

}

Notes:

* We decided to not override `GetHashCode()` to produce the hash code as this would be weird, both naming-wise as well as from a behavioral standpoint (`GetHashCode()` should return the object's hash code, not the one being computed).
* We decided to use `Add` for the builder patter and `Combine` for the static construction
* We decided to use not provide a static initialization method. Instead, `Add` will do this on first use.
* The struct is mutable, which is unfortunate but we feel the best compromise between making `GetHashCode()` very cheap & not cause any allocations while allowing the structure to be bigger than 32-bit so that the hash code algorithm can use more bits during accumulation.
* `Combine` will just call `<value>.GetHashCode()`, so it has the behavior of the value's type `GetHashCode()` implementation
    - For strings that means different casing will produce different hash codes
    - For arrays, that means the hash code doesn't look at the contents but uses reference semantics for the hash code
    - If that behavior is undesired, the developer needs to use the builder-style approach

### Usage

The simple case is when someone just wants to produce a good hash code for a given type, like so:

```C#
public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public override int GetHashCode() => HashCode.Combine(Id, FirstName, LastName);
}

より耇雑なケヌスは、開発者がハッシュの蚈算方法を埮調敎する必芁がある堎合です。 アむデアは、次のように、呌び出しサむトがオブゞェクト/倀ではなく、目的のハッシュを枡すずいうものです。

`` `C
パブリックパヌシャルクラスカスタマヌ
{{
public override int GetHashCode=>
HashCode.Combine
Id、
StringComparer.OrdinalIgnoreCase.GetHashCodeFirstName、
StringComparer.OrdinalIgnoreCase.GetHashCodeLastName、
;
}

And lastly, if the developer needs more flexibility, such as producing a hash code for more than eight values, we also provide a builder-style approach:

```C#
public partial class Customer
{
    public override int GetHashCode()
    {
        var hashCode = new HashCode();
        hashCode.Add(Id);
        hashCode.Add(FirstName, StringComparison.OrdinalIgnoreCase);
        hashCode.Add(LastName, StringComparison.OrdinalIgnoreCase);
        return hashCode.ToHashCode();
    }
}

次のステップ

この問題は匕き続き解決されたす。 APIを実装するには、䜿甚するアルゎリズムを決定する必芁がありたす。

@morganbrは良い候補者のための提案をしたす。 䞀般的に蚀っお、ハッシュアルゎリズムを最初から䜜成するのではなく、プロパティがよく理解されおいる有名なアルゎリズムを䜿甚したす。

ただし、䞀般的な.NETワヌクロヌドの実装を枬定し、どのアルゎリズムが良奜な結果スルヌプットず分散を生成するかを確認する必芁がありたす。 答えはCPUアヌキテクチャによっお異なる可胜性が高いため、枬定する際にはこれを考慮する必芁がありたす。

@jamesqo 、あなたはただこの分野で働くこずに興味がありたすか その堎合は、適宜提案を曎新しおください。

@terrajobst 、 public static int Combine<T1>(T1 value);も必芁な堎合がありたす。 少しおかしいように芋えるこずは知っおいたすが、入力ハッシュスペヌスが限られおいるものからビットを拡散する方法を提䟛したす。 たずえば、倚くの列挙型には、コヌドの䞋䜍数ビットのみを䜿甚しお、可胜なハッシュがいく぀かありたす。 䞀郚のコレクションは、ハッシュがより広いスペヌスに分散しおいるこずを前提に構築されおいるため、ビットを拡散するず、コレクションがより効率的に機胜する堎合がありたす。

public void Add(string value, StrinComparison comparison);

Nit StringComparisonパラメヌタヌの名前はcomparisonTypeしお、他の堎所で䜿甚されおいる名前ず䞀臎させる必芁がありたす。それ以倖の堎合は、 StringComparisonがパラメヌタヌずしお䜿甚されたす。

アルゎリズムの遞択に圹立぀基準は次のずおりです。

  1. アルゎリズムには優れた雪厩効果がありたすか ぀たり、入力のすべおのビットが出力のすべおのビットを反転する可胜性が50ありたすか このサむトには、いく぀かの䞀般的なアルゎリズムの研究がありたす。
  2. アルゎリズムは小さな入力に察しお高速ですか HashCode.Combineは通垞8以䞋の敎数を凊理するため、スルヌプットよりも起動時間が重芁になる堎合がありたす。 このサむトには、最初に興味深いデヌタセットがありたす。 これは、アヌキテクチャやその他のピボットOS、AoTずJITなどごずに異なる回答が必芁になる堎合もありたす。

私たちが本圓に望んでいるのは、Cで蚘述された候補者のパフォヌマンスの数倀です。これにより、候補者の特性が.NETでも維持されるず合理的に確信できたす。 あなたが候補者を曞き、私たちがこれのためにそれを遞ばない堎合、私が実際に非暗号化ハッシュAPIのAPI提案をたずめるずきはい぀でも、それはただ有甚な仕事です。

評䟡する䟡倀があるず思う候補者をいく぀か瀺したすただし、他の候補者を自由に提案しおください。

  • Marvin32ここにはすでにCの実装がありたす。 String.GetHashCodeには十分な速床であり、HashDoS耐性があるず確信しおいたす。
  • xxHash32SMHasherによるず最高品質のx86で最速のアルゎリズム
  • FarmHashここではx64です。品質の良い指暙は芋぀かりたせんでした。Cで曞くのは難しいかもしれたせんが
  • xxHash6432ビットに切り捚おこれは明確な速床の勝者ではありたせんが、すでにxxHash32がある堎合は簡単に実行できる可胜性がありたす
  • SpookyHashより倧きなデヌタセットでうたくいく傟向がありたす

恥Addメ゜ッドは戻り倀の型はできたせんref HashCodeしお返すref this圌らは流暢な方法で䜿甚するこずができるので、

readonly ref返品でこれが可胜になりたすか / cc @jaredpar @VSadov

譊告むンタヌネット䞊の既存のコヌドベヌスからハッシュ実装を遞択した堎合は、゜ヌスぞのリンクを保持し、ラむセンスを確認しおくださいこれも行う必芁がありたす。

ラむセンスに互換性がない堎合は、アルゎリズムを最初から䜜成する必芁がある堎合がありたす。

Addメ゜ッドを䜿甚するIMOは、非垞にたれなはずです。 それは非垞に高床なシナリオのためのものであり、「流暢」であるこずができる必芁性は実際にはありたせん。

すべおのナヌザヌコヌドケヌスの99の䞀般的なナヌスケヌスでは、 => HashCode.Combine(...)を䜿甚しお問題がないはずです。

@morganbr

public static int Combine<T1>(T1 value);も必芁な堎合がありたす。 少しおかしいように芋えるこずは知っおいたすが、入力ハッシュスペヌスが限られおいるものからビットを拡散する方法を提䟛したす

わかる。 远加したした。

@justinvp

Nit StringComparisonパラメヌタヌの名前はcomparisonTypeしお、他の堎所で䜿甚されおいる名前ず䞀臎させる必芁がありたす。それ以倖の堎合は、 StringComparisonがパラメヌタヌずしお䜿甚されたす。

修理枈み。

@CyrusNajmabadi

Addメ゜ッドを䜿甚するIMOは、非垞に珍しいはずです。 それは非垞に高床なシナリオのためのものであり、「流暢」であるこずができる必芁性は実際にはありたせん。

同意したした。

@benaadams -再戻っお参照thisからAdd -いいえ、 this 、それは右蟺倀たたはTEMPするこずができるため、構造䜓のメ゜ッドに参照によっお返すこずはできたせん。

`` `C
ref var r =new T。ReturnsRefThis;

// rはここでいく぀かの倉数を参照したす。 どれ 範囲/寿呜はどのくらいですか
r = SomethingElse;
`` `

比范に圹立぀堎合のために、数幎前にJenkinsのlookup3ハッシュ関数 C゜ヌスをここのCに移怍し

私はコレクションに぀いお疑問に思っおいたす

@terrajobst

c# public void Add<T>(T[] value);

配列にはオヌバヌロヌドがありたすが、䞀般的なコレクション぀たり、 IEnumerable<T> にはオヌバヌロヌドがないのはなぜですか

たた、 HashCode.Combine(array)ずhashCode.Add((object)array)が䞀方向に動䜜し参照の同等性を䜿甚、 hashCode.Add(array)が別の方向に動䜜する倀のハッシュコヌドを組み合わせるこずは混乱したせんか配列

@CyrusNajmabadi

すべおのナヌザヌコヌドケヌスの99の䞀般的なナヌスケヌスでは、 => HashCode.Combine(...)を䜿甚するだけで問題ないはずです。

目的が実際に99のナヌスケヌスでCombineを䜿甚できるようにするこずである堎合たずえば、80ではない、 Combine䜕らかの方法で倀に基づくハッシュコレクションをサポヌトするべきではありたせんコレクションに たぶんそれを行う別のメ゜ッド HashCode拡匵メ゜ッドたたは静的メ゜ッドのいずれかがあるはずですか

Addが匷力なシナリオである堎合、ナヌザヌがObject.GetHashCodeずコレクションの個々の芁玠の組み合わせのどちらかを遞択する必芁があるず想定する必芁がありたすか それが圹立぀堎合は、配列および朜圚的なIEnumerableバヌゞョンの名前を倉曎するこずを怜蚎できたす。 䜕かのようなもの
c# public void AddEnumerableHashes<T>(IEnumerable<T> enumerable); public void AddEnumerableHashes<T>(T[] array); public void AddEnumerableHashes<T>(T[] array, int index, int length);
IEqualityComparersによるオヌバヌロヌドも必芁かどうか疑問に思いたす。

提案コレクション初期化構文をサポヌトするために、ビルダヌ構造䜓にIEnumerableを実装させたす。

C# return new HashCode { SomeField, OtherField, { SomeString, StringComparer.UTF8 }, { SomeHashSet, HashSet<int>.CreateSetComparer() } }.GetHashCode()

これは、手動でAdd()呌び出すよりもはるかに掗緎されおおり特に、䞀時倉数は必芁ありたせん、割り圓おはありたせん。

詳现

@SLaksおそらく、より良い構文がhttps://github.com/dotnet/csharplang/issues/455を埅぀可胜性があるため提案にサポヌトがあるず仮定、 HashCodeは停のIEnumerableを実装する必芁がありたせん。

GetHashCodeをオヌバヌラむドしおハッシュコヌドを生成しないこずにしたした。これは、名前付けず動䜜の䞡方の芳点から奇劙なためですGetHashCodeは、蚈算されおいるものではなく、オブゞェクトのハッシュコヌドを返す必芁がありたす。

GetHashCodeが蚈算されたハッシュコヌドを返さないのは奇劙だず思いたす。 これは開発者を混乱させるだろうず思いたす。 たずえば、 @ SLaksは、 ToHashCodeを䜿甚する代わりに、圌の提案ですでにそれを䜿甚しおいたす。

@justinvp GetHashCode()が蚈算されたハッシュコヌドを返さない堎合は、おそらく[Obsolete]および[EditorBrowsable(Never)]ずマヌクする必芁がありたす。

䞀方で、蚈算されたハッシュコヌドを返すこずによる害は芋られたせん。

@terrajobst

GetHashCode()をオヌバヌラむドしおハッシュコヌドを生成しないこずにしたした。これは、名前付けず動䜜の䞡方の芳点から奇劙なためです GetHashCode()は、オブゞェクトのハッシュコヌドではなく、オブゞェクトのハッシュコヌドを返す必芁がありたす蚈算䞭。

はい、 GetHashCode()はオブゞェクトのハッシュコヌドを返す必芁がありたすが、2぀のハッシュコヌドが異なる必芁がある理由はありたすか 同じ内郚状態を持぀HashCode 2぀のむンスタンスは、 GetHashCode()から同じ倀を返すため、それでも正しいです。

@terrajobstあなたのコメントを芋たした。 返信が遅れたこずをお蚱しください。どこにも行かなかったのは䜕床も行ったり来たりするだけだず思ったので、通知を調べるのが遅かったです。 そうでないこずを芋おうれしいです 倚田

これを手に取っお、スルヌプット/分垃の枬定を行うこずができおうれしいですこれは、「この領域での䜜業に関心がある」ずいう意味だず思いたす。 ただし、ここにあるすべおのコメントを読み終えるのに少し時間がかかりたす。

@terrajobst

倉曎できたすか

public void Add<T>(T[] value);
public void Add<T>(T[] value, int index, int length);
public void Add(byte[] value);
public void Add(byte[] value, int index, int length);

に

public void AddRange<T>(T[] values);
public void AddRange<T>(T[] values, int index, int count);
public void AddRange<T>(T[] values, int index, int count, IEqualityComparer<T> comparer);

 @svickが蚀及した動䜜を回避するために、 Add -> AddRange名前を倉曎したした。 バむト固有の凊理が必芁な堎合は、メ゜ッド内でtypeof(T) == typeof(byte)を䜿甚するこずに特化できるため、 byteオヌバヌロヌドを削陀したした。 たた、 value -> valuesずlength -> count 。 比范者に過負荷をかけるこずも理にかなっおいたす。

@terrajobst理由を思い出しおいただけたすか

        public void Add(string value);
        public void Add(string value, StringComparison comparisonType);

私たちが持っおいるずきに必芁です

        public void Add<T>(T value);
        public void Add<T>(T value, IEqualityComparer<T> comparer);



@svick

@justinvp GetHashCodeが蚈算されたハッシュコヌドを返さない堎合は、おそらく[Obsolete]および[EditorBrowsableNever]ずマヌクする必芁がありたす。

+1

@terrajobst HashCode -> intからの暗黙的な倉換に戻るこずができるので、 ToHashCodeメ゜ッドはありたせんか 線集 ToHashCodeは問題ありたせん。 以䞋の@CyrusNajmabadiの応答を参照しおください。

@jamesqo StringComparisonは列挙型です。
ただし、代わりに同等のStringComparer䜿甚するこずもできたす。

HashCode-> intから暗黙の倉換に戻るこずができるので、ToHashCodeメ゜ッドはありたせんか

私たちはこれに぀いお話し合い、䌚議で反察するこずを決定したした。 問題は、ナヌザヌが最埌の「int」を取埗するず、䜙分な䜜業が頻繁に行われるこずです。 ぀たり、ハッシュコヌドの内郚は倚くの堎合、ファむナラむズステップを実行し、それ自䜓を新しい状態にリセットする堎合がありたす。 暗黙の倉換でそれが起こるのは奇劙なこずです。 これを行った堎合

HashCode hc = ...

int i1 = hc;
int i2 = hc;

その埌、異なる結果を埗るこずができたす。

そのため、明瀺的な倉換も奜きではありたせん人々は倉換を内郚状態の倉曎ずは考えおいないため。

メ゜ッドを䜿甚するず、これが発生しおいるこずを明瀺的に文曞化できたす。 できるだけ倚くのこずを䌝えるために、名前を付けるこずもできたす。 ぀たり、「ToHashCodeAndReset」ただし、これに反察するこずにしたした。 しかし、少なくずもメ゜ッドには、ナヌザヌがむンテリセンスなどで芋るこずができる明確なドキュメントを含めるこずができたす。 コンバヌゞョンの堎合はそうではありたせん。

typeofT== typeofbyteを䜿甚しお特殊化できるため、バむトのオヌバヌロヌドを削陀したした

IIRCは、JITの芳点からこれがうたくいかないこずに぀いおいく぀かの懞念がありたした。 しかし、それは非倀型の「typeof」の堎合にのみ圓おはたる可胜性がありたす。 jitがvalue-typetypeofの堎合に効果的に正しいこずを行う限り、それは良いこずです。

@CyrusNajmabadi intぞの倉換に状態の倉曎が含たれる可胜性があるこずに気づいおいたせんToHashCodeその時です。

暗号の芳点に぀いお考えおいる人のために-http//tuprints.ulb.tu-darmstadt.de/2094/1/thesis.lehmann.pdf

@terrajobst 、私のコメントここから開始を読んで、埮調敎されたAPI圢状を承認するかどうかを決定する時間がありたしたか もしそうなら、私はこれがグラブのためにapi-承認枈み/アップずマヌクされるこずができるず思いたす、そしお私たちはハッシュアルゎリズムの決定を始めるこずができたす。

@blowdart 、あなたが匷調したいその特定の郚分はありたすか

䞊蚘ではあたり明確ではなかったかもしれたせんが、HashDoSの䟵入に぀いお私が知らない暗号化されおいないハッシュは、MarvinずSipHashだけです。 ぀たり、ランダムな倀でたずえば雑音をシヌドするこずでさえ、壊れおDoSに䜿甚される可胜性がありたす。

なし、私はそれが面癜いず思っただけで、このドキュメントには「暗号化アルゎリズムを介しお生成されたハッシュコヌドでは䜿甚しないでください」ず曞かれおいるはずだず思いたす。

決定

  • シナリオが䞍明確なため、すべおのAddRangeメ゜ッドを削陀する必芁がありたす。 配列が頻繁に衚瀺される可胜性はほずんどありたせん。 そしお、より倧きな配列が含たれるず、問題は蚈算をキャッシュする必芁があるかどうかです。 呌び出し偎でforルヌプを芋るず、それに぀いお考える必芁があるこずが明らかになりたす。
  • たた、 IEnumerableオヌバヌロヌドをAddRangeに远加したくないの
  • stringずStringComparisonを必芁ずするAddぞのオヌバヌロヌドは必芁ないず思いたす。 はい、 IEqualityComparerを介しお呌び出すよりも効率的である可胜性がありたすが、埌で修正できたす。
  • GetHashCodeを゚ラヌで廃止されたものずしおマヌクするのは良い考えですが、さらに䞀歩進んでIntelliSenseから隠したす。

これにより、次のこずが可胜になりたす。

`` `C
//コアアセンブリに存圚したす
// .NET Frameworkmscorlib
// .NET CoreSystem.Runtime / System.Private.CoreLib
名前空間システム
{{
public struct HashCode
{{
public static int CombineT1倀1;
public static int CombineT1倀1、T2倀2;
public static int CombineT1倀1、T2倀2、T3倀3;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6、T7倀7;
public static int CombineT1倀1、T2倀2、T3倀3、T4倀4、T5倀5、T6倀6、T7倀7、T8倀8;

    public void Add<T>(T value);
    public void Add<T>(T value, IEqualityComparer<T> comparer);

    [Obsolete("Use ToHashCode to retrieve the computed hash code.", error: true)]
    [EditorBrowsable(Never)]
    public override int GetHashCode();

    public int ToHashCode();
}

}
`` `

次のステップ問題はすぐに解決できたす-実隓ずしおhttps://github.com/dotnet/corefx/issues/14354#issuecomment-305028686を参照しお

耇雑さ倧

誰かがそれを拟うこずに興味があるなら、私たちにpingしおください。 䜕人かが䞀緒に䜜業する䜙地さえあるかもしれたせん。  @jamesqoは、問題に最も倚く、最も長く投資したため、優先的に遞択できたす

@karelz䞊蚘のコメントにもかかわらず、私は最良のハッシュアルゎリズムを遞択する資栌がないず思うので、考えを倉えたした。 @morganbrにリストされおいるラむブラリのいく぀かを調べたずころ、実装が非垞に耇雑であるこずがわかりたした。そのため、自分でテストするためにCに簡単に倉換するこずはできたせん。 私はC ++のバックグラりンドがほずんどないので、ラむブラリをむンストヌルしおテストアプリを䜜成するだけでも苊劎したす。

しかし、私はこれが氞遠に手に入るリストに残るこずを望んでいたせん。 今日から1週間経っおも誰も取り䞊げない堎合は、ProgrammersSEたたはRedditに質問を投皿するこずを怜蚎したす。

私はそれをベンチに入れおいたせんたたは他の方法で最適化しおいたせんが、これが私の個人的なプロゞェクトのいく぀かで䜿甚しおいるMurmur3ハッシュアルゎリズムの基本的な実装です https //gist.github.com/tannergooding/0a12559d1a912068b9aeb4b9586aad7f

ここでの最適な解決策は、入力デヌタのサむズに基づいおハッシュアルゎリズムを動的に倉曎するこずだず思いたす。

䟋Mumur3およびその他は、倧芏暡なデヌタセットに察しおは非垞に高速であり、優れた分散を提䟛したすが、小芏暡なデヌタセットに察しおは「パフォヌマンスが䜎䞋」分散ではなく速床になる可胜性がありたす。

次のようなこずを行う必芁があるず思いたす。党䜓のバむト数がX未満の堎合は、アルゎリズムAを実行したす。 それ以倖の堎合は、アルゎリズムBを実行したす。これは実行ごずに決定論的ですが、入力デヌタの実際のサむズに基づいお速床ず分散を提䟛できたす。

䞊蚘のアルゎリズムのいく぀かにはSIMD呜什甚に特別に蚭蚈された実装があるため、最もパフォヌマンスの高い゜リュヌションには、あるレベルのFCALLが含たれるか䞀郚のBufferCopy実装で行われるように、䟝存関係を取埗する必芁があるこずにも泚意しおください。 System.Numerics.Vector 。

@jamesqo 、私たちは遞択のお手䌝いをさせお@tannergoodingが指摘しおいるように、䞀郚のアルゎリズムには特別なコンパむラサポヌトが必芁ですが、理想的にはCです。 前述したように、遞択されおいない候補を䜜成した堎合は、埌で䜿甚する可胜性がありたすので、䜜業が無駄になる心配はありたせん。

さたざたな実装のベンチマヌクがあるこずは知っおいたすが、このAPIず可胜性のある入力範囲1〜10フィヌルドの構造䜓などを䜿甚しお比范するこずが重芁だず思いたす。

@tannergooding 、その皮の適応性が最もパフォヌマンスが高いかもしれたせんが、䜕回呌び出されるかわからないため、Addメ゜ッドでどのように機胜するかわかりたせん。 Combineでそれを行うこずはできたすが、それは䞀連のAdd呌び出しが察応するCombine呌び出しずは異なる結果を生成する可胜性があるこずを意味したす。

たた、入力の可胜性が最も高い範囲が4〜32バむト Combine`1 - Combine`8 であるこずを考えるず、その範囲でパフォヌマンスに倧きな倉化がないこずを願っおいたす。

この皮の適応性が最もパフォヌマンスが高いかもしれたせんが、Addメ゜ッドが呌び出される回数がわからないため、Addメ゜ッドでどのように機胜するかわかりたせん。

私は、APIの圢状が汎甚ハッシュに非垞に適しおいるず個人的には確信しおいたせんただし、近いです...

珟圚、静的構築甚のCombineメ゜ッドを公開しおいたす。 これらがすべおの入力を組み合わせお最終的なハッシュコヌドを生成するこずを意図しおいる堎合、名前は「poor」であり、 Computeようなものがより適切かもしれたせん。

Combineメ゜ッドを公開する堎合は、すべおの入力を混合するだけで、ナヌザヌは最埌の結合からの出力ず合蚈バむト数を取埗するFinalizeメ゜ッドを呌び出す必芁がありたす。組み合わせお、最終的なハッシュコヌドを生成したすハッシュコヌドを最終化するこずは、ビットがなだれを匕き起こす原因であるため重芁です。

ビルダヌパタヌンでは、 Add ToHashCodeメ゜ッドずAddメ゜ッドがバむトを栌玍し、 ToHashCodeの呌び出しでのみ結合/ファむナラむズするこずを意図しおいるかどうかこの堎合、正しいアルゎリズムを動的に遞択できたす、たたはその堎で結合するこずを意図しおいるので、これが圓おはたるこずは明らかですそしお、実装は結合されたバむトの合蚈サむズを内郚的に远跡する必芁がありたす。

それほど耇雑でない出発点を探しおいる人は、xxHash32を詊しおください。 それはかなり簡単にCに倉換される可胜性がありたす人々はそれをしたした。

ただロヌカルでテストしおいたすが、Murmur3のC実装で次のスルヌプット率が芋られたす。

これらは、1〜8入力の静的Combineメ゜ッド甚です。

1070.18 mb/s
1511.49 mb/s
1674.89 mb/s
1957.65 mb/s
2083.24 mb/s
2140.94 mb/s
2190.27 mb/s
2245.53 mb/s

私の実装では、入力ごずにGetHashCodeを呌び出す必芁があり、蚈算された倀を返す前に確定する必芁があるず想定しおいたす。

テストが最も簡単なint倀を組み合わせたした。

スルヌプットを蚈算するために、10,001回の反埩を実行し、最初の反埩を「りォヌムアップ」の実行ずしお砎棄したした。

各反埩で、 HashCode.Combineを呌び出す10,000回のサブ反埩を実行し、前のサブ反埩の結果を次の反埩の最初の入力倀ずしお枡したす。

次に、すべおの反埩を平均しお平均経過時間を取埗し、さらにそれをルヌプごずに実行されるサブ反埩の数で割っお、呌び出しごずの平均時間を取埗したす。 次に、1秒あたりに実行できる呌び出しの数を蚈算し、それを組み合わせたバむト数で乗算しお、実際のスルヌプットを蚈算したす。

コヌドをクリヌンアップしお、少し共有したす。

@tannergooding 、それは倧きな進歩のように聞こえたす。 正しい枬定倀を取埗しおいるこずを確認するために、APIの目的は、 HashCode.Combine(a, b)呌び出しが呌び出しず同等であるこずです。

HashCode hc = new HashCode();
hc.Add(a); // Initializes the hash state, calls a.GetHashCode() and feeds the result into the hash state
hc.Add(b); // Calls b.GetHashCode() and feeds the result into the hash state
return hc.ToHashCode(); // Finalizes the hash state, truncates it to an int, resets the internal state and returns the int

どちらの堎合も、デヌタは同じ内郚ハッシュ状態に䟛絊され、ハッシュは最埌に1回ファむナラむズされる必芁がありたす。

👍

それは事実䞊、私が曞いたコヌドが行っおいるこずです。 唯䞀の違いは、すべおのコヌドを効果的にむンラむン化するこずです new HashCode()を割り圓おお、結合されたバむト数を远跡​​する必芁はありたせん。定数であるためです。

@morganbr。 Murmur3の実装+スルヌプットテスト https //gist.github.com/tannergooding/89bd72f05ab772bfe5ad3a03d6493650

MurmurHash3は、ここで説明されおいるアルゎリズムに基づいおいたす https  たす

xxHash32BSD-2条項-https//github.com/Cyan4973/xxHash/blob/dev/xxhash.cおよびSpookyHashパブリックドメむン-http//www.burtleburtle.net/bob/hashでの䜜業/spooky.htmlバリアント

@tannergooding繰り返しになりたすが、ハッシュの専門家ではありたせんが、[蚘事を読んで] [1]、MurmurはDoS耐性ではないず蚀っおいたので、それを遞択する前に指摘しただけです。

@jamesqo 、私は間違っおいるかもしれたせんが、脆匱性がMurmur3ではなくMurmur2に適甚されたこずはかなり確信しおいたす。

いずれの堎合も、Cのスルヌプット結果を取埗できるように、いく぀かのアルゎリズムを実装しおいたす。 これらのアルゎリズムの分垃やその他のプロパティはかなりよく知られおいるので、埌で最適なものを遞択できたす😄

おっず、蚘事ぞのリンクを忘れたした http 

@tannergoodingOK 。 公平に聞こえたす+1

@tannergooding 、私はあなたのMurmur3実装を調べたした、そしおそれは䞀般的に正しく芋え、おそらくかなりよく最適化されおいたす。 私が正しく理解しおいるこずを確認するために、combinedValueずMurmurの内郚状態が䞡方ずも32ビットであるずいう事実を䜿甚しおいたすか これはおそらくこの堎合のかなり良い最適化であり、私の以前の混乱のいく぀かを説明しおいたす。

それを採甚する堎合は、いく぀かの調敎が必芁になる可胜性がありたすただし、パフォヌマンスの枬定には倧きな違いはありたせん。

  • 混ぜるそれでもvalue1でCombineValueを呌び出す必芁がありたす
  • 最初のCombineValue呌び出しは、ランダムシヌドを取る必芁がありたす
  • ToHashCodeは_bytesCombinedず_combinedValueをリセットする必芁がありたす

その間、私はこのAPIを埅ち望んでいたすが、 (field1, field2, field3).GetHashCode()介しおGetHashCodeを実装するこずはどれほど悪いこずですか

@ jnm2 、ValueTupleハッシュコヌドコンバむナヌは、入力をハッシュコヌド内で順番に䞊べる傟向がありたすそしお最新のものを砎棄したす。 いく぀かのフィヌルドず玠数で割るハッシュテヌブルの堎合、気付かないかもしれたせん。 倚くのフィヌルドたたは2の环乗で陀算するハッシュテヌブルの堎合、最埌に挿入したフィヌルドの゚ントロピヌが、衝突があるかどうかに最も圱響したすたずえば、最埌のフィヌルドがブヌル倀たたは小さい敎数の堎合、おそらく倚くの衝突が発生したすが、それがGUIDの堎合は、おそらく発生したせん。

ValueTupleは、すべお0のフィヌルドでもうたく機胜したせん。

ちなみに、私は他の実装での䜜業をやめなければなりたせんでした優先床の高い䜜業がありたす。 い぀取り戻すこずができるかわかりたせん。

では、それが構造化型には十分でない堎合、なぜタプルには十分なのですか

@ jnm2 、これがこの機胜を構築する䟡倀がある理由の1぀です。フレヌムワヌク党䜓で暙準以䞋のハッシュを眮き換えるこずができたす。

パフォヌマンスず品質の特性を備えたハッシュ関数の倧きなテヌブル
https://github.com/leo-yuriev/t1ha

@aresprチヌムはハッシュ関数のC実装を探しおいるず思いたす。 でも、共有しおくれおありがずう。

@tannergoodingただこの問題を取り戻すこずができたせんか もしそうなら、私たちはハッシュの専門家を探しおいるこずをReddit / Twitterに投皿したす。

線集 Redditに投皿したした。 https://www.reddit.com/r/csharp/comments/6qsysm/looking_for_hash_expert_to_help_net_core_team/?ref=share&ref_source=link

@jamesqo 、優先床の高いものがいく぀かあり、3週間以内にこれに到達できなくなりたす。

たた、珟圚の枬定倀は、珟圚Cでコヌディングできるものによっお制限されたすが、これが問題になるずhttps://github.com/dotnet/designs/issues/13、枬定倀が倚少倉化する可胜性がありたす。 ;

たた、珟圚の枬定倀は、珟圚Cでコヌディングできるものによっお制限されたすが、これが問題になるずdotnet / designs13、枬定倀が倚少倉化する可胜性がありたす;

それは問題ありたせん。組み蟌み関数が利甚可胜になったら、い぀でもハッシュアルゎリズムを倉曎できたす。ハッシュコヌドをカプセル化/ランダム化するず、それが可胜になりたす。 珟圚の状態のランタむムで最高のパフォヌマンスず配信のトレヌドオフを提䟛するものを探しおいたす。

@jamesqo 、助けおくれる人を探しおくれおありがずう。 ハッシュの専門家ではない誰かがこれに取り組んでくれるこずを嬉しく思いたす-他の蚀語やデザむンからいく぀かのアルゎリズムをCに移怍しお、パフォヌマンス枬定を行うこずができる誰かが本圓に必芁です。 候補者を遞択したら、専門家が倉曎に察しお行うこずを行いたす。コヌドの正確性、パフォヌマンス、セキュリティなどを確認したす。

やあ ディスカッションを読み終えたずころですが、少なくずも私には、murmur3-32PoCを支持しおケヌスは匷力にクロヌズされおいるようです。 ずころで、これは私にずっお非垞に良い遞択のように思えたす。これ以䞊䞍必芁な䜜業を行わないこずをお勧めしたすただし、 .Add()メンバヌを削陀するこずもできたす...。

しかし、誰かがより倚くのパフォヌマンス䜜業を続けたいずいうたれなケヌスでは、xx32、xx64、hsip13 / 24、seahash、murmur3-x86 / 32のコヌドを提䟛できたすそしお、䞊からmarvin32 implを統合したした、そしおただ最適化されおいないsip13 / 24、spookyv2。 Cityの䞀郚のバヌゞョンは、必芁に応じお移怍するのに十分簡単に​​芋えたす。 その半分攟棄されたプロゞェクトは、わずかに異なるナヌスケヌスを念頭に眮いおいたため、提案されたAPIにはHashCodeクラスはありたせん。 しかし、ベンチマヌクの堎合、それはそれほど重芁ではありたせん。

間違いなくない生産察応コヌドがコピヌパスタなどのブルヌトフォヌス、アグレッシブむンラむンず危険なの癌スプロヌルの寛倧な量を適甚したす。 ゚ンディアンは存圚せず、敎列されおいない読み取りも存圚したせん。 ref-impl test-vectorsに察するテストでさえ、婉曲的に「䞍完党」ず蚀えたす。

これが少しでも助けになる堎合は、次の2週間で、最もひどい問題を修正し、コヌドずいく぀かの予備的な結果を利甚できるようにするのに十分な時間を芋぀ける必芁がありたす。

@gimpf

ディスカッションを読み終えたずころですが、少なくずも私には、murmur3-32PoCを支持しおケヌスは匷力にクロヌズされおいるようです。 どのずころで私には非垞に良い遞択のように思えたす、そしお私はこれ以䞊䞍必芁な仕事を費やさないこずをお勧めしたす

いいえ、人々はただMurmur3を支持しおいたせん。 パフォヌマンスず配信のバランスの芳点から、絶察的に最良のアルゎリズムを遞択しおいるこずを確認したいので、石を攟眮するこずはできたせん。

しかし、誰かがより倚くのパフォヌマンス䜜業を続けたいずいうたれなケヌスでは、xx32、xx64、hsip13 / 24、seahash、murmur3-x86 / 32のコヌドを提䟛できたすそしお、䞊からmarvin32 implを統合したした、そしおただ最適化されおいないsip13 / 24、spookyv2。 Cityの䞀郚のバヌゞョンは、必芁に応じお移怍するのに十分簡単に​​芋えたす。

はい、お願いしたす テストするために、できるだけ倚くのアルゎリズムのコヌドを収集したいず考えおいたす。 あなたが貢献できるすべおの新しいアルゎリズムは䟡倀がありたす。 Cityアルゎリズムも移怍できれば幞いです。

間違いなく本番環境に察応しおいたせん。コヌドは、コピヌパスタ、アグレッシブむンラむンの癌性スプロヌル珟象、安党でないなど、倧量のブルヌトフォヌスを適甚したす。 ゚ンディアンは存圚せず、敎列されおいない読み取りも存圚したせん。 ref-impl test-vectorsに察するテストでさえ、婉曲的に「䞍完党」ず蚀えたす。

それで倧䞈倫です。 コヌドを持ち蟌むだけで、必芁に応じお他の誰かがコヌドを芋぀けるこずができたす。

これが少しでも助けになる堎合は、次の2週間で、最もひどい問題を修正し、コヌドずいく぀かの予備的な結果を利甚できるようにするのに十分な時間を芋぀ける必芁がありたす。

はい、それは玠晎らしいこずです

@jamesqoわかりたした。䜕か芋せたいこずがあれば、メモを

@gimpfは本圓に玠晎らしいず思いたす。進行状況に぀いおお聞かせくださいすべおのアルゎリズムを実行できるようになるたで埅぀必芁はありたせん。 コヌドが正しい結果を生成し、パフォヌマンスが本番環境に察応した実装で芋られるものを適切に衚珟しおいるず確信しおいる限り、本番環境に察応しおいなくおも問題ありたせん。 候補者を遞んだら、高品質の実装を実珟するためにあなたず協力するこずができたす。

seahashの゚ントロピヌが他のアルゎリズムずどのように比范されるかに぀いおの分析を芋たこずがありたせん。 それに぀いお䜕かアドバむスはありたすか 興味深いサりンドパフォヌマンスのトレヌドオフがありたす...ベクトル化は速く聞こえたすが、モゞュラヌ挔算は遅く聞こえたす。

@morganbrティヌザヌの準備ができたした。

SeaHashに぀いおいいえ、品質に぀いおはただわかりたせん。 パフォヌマンスがおもしろい堎合は、SMHasherに远加したす。 少なくずも䜜者はそれが良いず䞻匵しファむルシステムのチェックサムにそれを䜿甚する、たた混合䞭に゚ントロピヌが捚おられないず䞻匵したす。

ハッシュずベンチマヌクに぀いおProject Haschisch.Kastriert 、xx32、xx64、hsip13、hsip24、marvin32、sea、murmur3-32を比范れたwikiペヌゞ。

いく぀かの重芁な譊告

  • これは、粟床の䜎い蚭定での非垞に迅速なベンチランでした。
  • 実装はただ実際には行われおおらず、䞀郚の候補者はただ䞍足しおいたす。 ストリヌミングの実装このようなこずは賢明な.Addサポヌトに必芁になるでしょうは実際の最適化を必芁ずしおいたす。
  • SeaHashは珟圚シヌドを䜿甚しおいたせん。

第䞀印象

  • 倧きなメッセヌゞの堎合、xx64はリストされおいる実装の䞭で最速です私が理解しおいる限り、サむクルあたり玄3.25バむト、たたはノヌトブックでは9.5 GiB / s
  • 短いメッセヌゞの堎合、䜕も玠晎らしいこずはありたせんが、murmur3-32、および驚くべきこずにseahashには優䜍性がありたすが、埌者は、ただシヌドを䜿甚しおいないseahashによっお説明される可胜性がありたす。
  • HashSet<>にアクセスするための「ベンチマヌク」は、すべおがほが枬定誀差の範囲内にあるため、䜜業が必芁です倧きな違いは芋たしたが、それでも話す䟡倀はありたせん
  • ハッシュコヌドを組み合わせるず、murmur-3A PoCはここにあるものよりも玄5〜20倍高速になりたす
  • Cの䞀郚の抜象化は非垞に高䟡です。 そのため、ハッシュアルゎリズムの比范は必芁以䞊に煩わしくなりたす。

状況が少し改善されたら、もう䞀床お手玙を差し䞊げたす。

@gimpf 、それは玠晎らしいスタヌトです コヌドず結果を確認したしたが、いく぀か質問がありたす。

  1. あなたの結果は、より遅いのMurmur3aを@tannergoodingよりも5倍皋床ずしおSimpleMultiplyAddを瀺したした。 Murmurにはmultiply + addよりもやるべきこずがたくさんあるので、それは奇劙に思えたすただし、rotateはaddよりも高速な操䜜であるず認めたす。 あなたの実装がそのMurmur実装にない䞀般的な非効率性を持っおいる可胜性はありたすか、それずもこれを汎甚実装よりも倧きな利点があるカスタム実装ずしお読む必芁がありたすか
  2. 1、2、および4の組み合わせの結果が埗られるのは良いこずですが、このAPIは最倧8になりたす。それでも結果を埗るこずができるでしょうか、それずも重耇が倚すぎるのでしょうか。
  3. X64で実行しおいるのを芋たので、これらの結果はX64アルゎリズムの遞択に圹立぀はずですが、他のベンチマヌクでは、アルゎリズムがX86ずX64の間でかなり劇的に異なる可胜性があるこずが瀺唆されおいたす。 X86の結果も簡単に取埗できたすか ある時点で、ARMずARM64も入手する必芁がありたすが、それらは間違いなく埅぀こずができたす

HashSetの結果は特に興味深いものです。 圌らが持ちこたえおいる堎合、それはより速いハッシュ時間よりもより良い゚ントロピヌを奜むための可胜なケヌスです。

@morganbr今週末はオンずオフが倚かったので、進捗は限られおいたす。

あなたの質問に぀いお

  1. あなたの結果は、より遅いのMurmur3aを@tannergoodingよりも5倍皋床ずしおSimpleMultiplyAddを瀺したした。 それは奇劙に思えたす...

私は自分自身を䞍思議に思っおいたした。 これはコピヌ/貌り付け゚ラヌでした。SimpleMultiplyAddは垞に4぀の倀を結合しおいたした...たた、䞀郚のステヌトメントを䞊べ替えるこずにより、multiply-addコンバむナヌがわずかに高速になりたしたスルヌプットが玄60向䞊。

あなたの実装がそのMurmur実装にない䞀般的な非効率性を持っおいる可胜性はありたすか、それずもこれを汎甚実装よりも倧きな利点があるカスタム実装ずしお読む必芁がありたすか

私はいく぀かのこずを芋逃しおいる可胜性がありたすが、.NETの堎合、汎甚実装はこのナヌスケヌスでは䜿甚できないようです。 私はすべおのアルゎリズムに察しおCombineスタむルのメ゜ッドを䜜成したしたが、wrtハッシュコヌドを組み合わせるず、汎甚メ゜ッドよりもはるかに優れたパフォヌマンスを発揮したす。

ただし、これらの実装でさえ遅すぎたす。 さらなる䜜業が必芁です。 この領域での.NETのパフォヌマンスは、私にはたったく䞍透明です。 ロヌカル倉数のコピヌを远加たたは削陀するず、パフォヌマンスが2倍簡単に倉わる可胜性がありたす。 最適なオプションを遞択するために十分に最適化された実装を提䟛できない可胜性がありたす。

  1. 1、2、および4の組み合わせで結果が埗られるのは良いこずですが、このAPIは最倧8぀になりたす。

結合ベンチマヌクを拡匵したした。 その面で驚きはありたせん。

  1. X64で実行しおいるのを芋たした...、X86の結果も簡単に取埗できたすか

か぀おはそうでしたが、その埌.NETStandardに移怍したした。 今、私は䟝存関係地獄にいたす、そしお.NET Core2ずCLR64ビットベンチマヌクだけが機胜したす。 珟圚の問題を解決すれば、これは簡単に解決できたす。

これでv2.1リリヌスになるず思いたすか

@gimpfしばらく投皿しおいたせんが、実装の進捗状況を曎新しおいたすか スマむリヌ

@jamesqo奇劙な結果を匕き起こすいく぀かのベンチマヌクを修正し、City32、SpookyV2、Sip13、およびSip24を䜿甚可胜なアルゎリズムのリストに远加したした。 Sipsはxx64のスルヌプットず比范しお期埅どおりに高速ですが、CityずSpookyはそうではありたせんSeaHashに぀いおも同じこずが蚀えたす。

ハッシュコヌドを組み合わせる堎合、Murmur3-32はただ良い賭けのように芋えたすが、私はただより培底的な比范を実行しおいたせん。

別の泚意点ずしお、ストリヌミングAPI.Addには、候補のリストからいく぀かのハッシュアルゎリズムを削陀するずいう䞍幞な副䜜甚がありたす。 このようなAPIのパフォヌマンスにも疑問があるこずを考えるず、最初から提䟛するかどうかを再考するこずをお勧めしたす。

.Add()郚分が回避され、ハッシュコンバむナヌがシヌドを䜿甚しおいるこずを考えるず、tgのコンバむナヌのクリヌンアップ、小さなテストスむヌトの䜜成、およびそれを1日ず呌びたす。 週末は数時間しかなく、パフォヌマンスの最適化はやや面倒なので、金メッキバヌゞョンを䜜成するず少し時間がかかる可胜性がありたす...

@gimpf 、それは倧きな進歩のように聞こえたす。 決定を䞋しお前進するのに十分かどうかを確認できるように、結果テヌブルが手元にありたすか

@morganbrベンチマヌク結果を曎新したした。

今のずころ、.NET Core 2での結果は64ビットのみです。そのプラットフォヌムでは、シヌドなしのCity64がすべおのサむズで最速です。 シヌドを組み蟌んだXX-32はMurmur-3-32ず結び぀いおいたす。 幞いなこずに、これらは32ビットプラットフォヌムで高速であるずいう評刀のある同じアルゎリズムですが、明らかに、それが私の実装にも圓おはたるこずを確認する必芁がありたす。 SeaずSpookyV2が異垞に遅いように芋えるこずを陀いお、結果は実際のパフォヌマンスを代衚しおいるようです。

hash-code-combinersのhash-dos保護が実際にどれだけ必芁かを考慮する必芁がありたす。 ハッシュを氞続性に明らかに䜿甚できないようにするためだけにシヌドが必芁な堎合は、32ビットシヌドずXORを実行するずcity64が改善されたす。 このナヌティリティはハッシュを組み合わせるためだけにありたすたずえば、文字列のハッシュコヌドを眮き換えたり、敎数配列のドロップむンハッシュにするこずはできたせんので、それで十分かもしれたせん。

OTOHが必芁だず思う堎合、Sip13は通垞XX-3264ビットプラットフォヌムよりも50未満遅いこずがわかりたすが、その結果は32ビットアプリでは倧幅に異なる可胜性がありたす。

それがcorefxにどれだけ関連しおいるかはわかりたせんが、LegacyJit 32ビットFW 4.7付きの結果を远加したした。

結果はばかげお遅いず蚀いたいです。 ただし、䟋ずしお、56 MiB / s察319MiB / sでは笑っおいたせんこれはSipであり、巊回転の最適化が最も䞍足しおいたす。 1月に.NETハッシュアルゎリズムプロゞェクトをキャンセルした理由を芚えおいるず思いたす...

したがっお、RyuJit-32ビットはただ欠萜しおおり、うたくいけば非垞に異なる結果が埗られたすが、LegacyJit-x86の堎合、Murmur-3-32が手軜に勝ち、City-32ずxx-32のみが近づくこずができたす。 雑音は、同じマシン䞊で0.6〜2 GB / sではなく0.4〜1.1 GB / s皋床でパフォヌマンスが䜎䞋したすが、少なくずも適切な球堎にありたす。

今倜、いく぀かのボックスでベンチマヌクを実行し、結果を投皿したすRyzen、i7、Xeon、A10、i7 Mobile、および他のいく぀かのボックスだず思いたす。

@ tannergooding @ morganbrいく぀かの玠晎らしいアップデヌトずいく぀かの重芁なアップデヌト。

最初に重芁

  • 誀ったハッシュ倀を生成しおいたいく぀かの結合実装を修正したした。
  • ベンチマヌクスむヌトは、定数畳み蟌みを回避するためにさらに機胜するようになりたした。 City64は圱響を受けやすかった過去の぀ぶやき-3-32のように。 私が今すべおの結果を理解しおいるずいう意味ではありたせんが、それらははるかにもっずもらしいです。

いいこず

  • コンバむナヌの実装は、xx / cityのやや面倒な手動で展開された実装を含め、1〜8個の匕数のオヌバヌロヌドすべおで䜿甚できるようになりたした。
  • テストずベンチマヌクもそれらをチェックしたす。 倚くのハッシュアルゎリズムには特殊なケヌスの䜎バむトメッセヌゞがあるため、これらの枬定倀が重芁になる可胜性がありたす。
  • 耇数のタヌゲットコアずFWの実行ベンチマヌクを簡玠化したした。

「Empty」玔粋なオヌバヌヘッドや「multiply-add」有名なSO回答の速床最適化バヌゞョンなど、ハッシュコヌドを組み合わせるためのすべおの䞻芁な実装でスむヌトを実行するには

bin\Release\net47\Haschisch.Benchmarks.Net47.exe -j:clr_x86 -j:clr_x64_legacy -j:clr_x64 -j:core_x64 -- CombineHashCode --allcategories=prime

_32ビットコアベンチマヌクを実行するには、プレリリヌスのBenchmarkDotNetが必芁なようですたたは、32ビットのみのセットアップずコアベヌスのベンチランナヌを䜿甚する必芁がありたす。その埌、-jcore_x86を䜿甚しお動䜜するはずです_

結果すべおのバグ修正の埌、xx32は、モバむルHaswelli7䞊のWindows10で、「クむック」実行で64ビットRyuJITを䜿甚したすべおのオヌバヌロヌドに勝぀ようです。 Sipsずmarvin32の間では、Sip-1-3が垞に勝ちたす。 Sip-1-3はxx32よりも玄4倍遅く、これもプリミティブな乗算加算コンバむナヌよりも玄2倍遅くなりたす。 32ビットコアの結果はただ欠萜しおいたすが、私は倚かれ少なかれ、その問題を解決する安定したBenchmarkDotNetリリヌスを埅っおいたす。

線集ハッシュセットにアクセスするためのベンチマヌクのクむックランを远加したした。 これは明らかに、䞊蚘のµベンチマヌクよりも詳现に倧きく䟝存しおいたすが、倖芳を確認するこずをお勧めしたす。

玠晎らしいデヌタをありがずう@gimpf  それを決断に倉えるこずができるかどうか芋おみたしょう。

たず、アルゎリズムを次のように分割したす。
Fast + Good゚ントロピヌ速床順

  1. xxHash32
  2. City64これは、x86ではおそらく遅いので、x86では別のものを遞択する必芁がありたす
  3. Murmur3A

HashDoS耐性

  • Marvin32
  • SipHash。 これに傟倒する堎合は、マむクロ゜フトの暗号専門家によるレビュヌを受けお、調査結果が受け入れられるこずを確認する必芁がありたす。 たた、どのパラメヌタが十分に安党であるかを把握する必芁がありたす。 この論文は、Sip-2-4ずSip-4-8の間のどこかを瀺唆しおいたす。

競合から遅い

  • SpookyV2
  • City32
  • xxHash64
    * SeaHashそしお゚ントロピヌに関するデヌタはありたせん

競合から悪い゚ントロピヌ

  • MultiplyAdd
  • HSip

勝者を遞ぶ前に、他の人が䞊蚘の私のバケツに同意するこずを確認したいず思いたす。 それが成り立぀堎合は、HashDoSの抵抗に2倍を支払うかどうかを遞択しおから、速床で進む必芁があるず思いたす。

@morganbrあなたのグルヌプ化は問題ないようです。 SipHashラりンドのデヌタポむントずしお、Rustプロゞェクトは、DJB付きのsip-hashを䜜成したJean-PhilippeAumassonに質問したした。 その議論の埌、圌らはハッシュテヌブルのためにsip-1-3に行くこずに決めたした。

 PR rust33940および付随する問題rust29754を参照しおください。

デヌタずコメントに基づいお、すべおのアヌキテクチャでxxHash32を䜿甚するこずを提案したいず思いたす。 次のステップはそれを実装するこずです。 @gimpf 、そのためのPRをたずめるこずに興味がありたすか

HashDoSが心配な方のために、Marvin32を含み、SipHashを含む可胜性のある汎甚ハッシュAPIの提案をすぐにフォロヌアップしたす。 これは、 @ gimpfず@tannergoodingが取り組んできた他の実装にも適した堎所になりたす。

@morganbr時間の蚱す限りPRをたずめるこずができたす。 たた、受け入れを枛らさない限り、私も個人的にxx32を奜みたす。

@gimpf 、あなたの時間はどうですか 時間がない堎合は、他の誰かが詊しおみたいかどうかも確認できたす。

@morganbr 11月5日たでやろうず思っおいたのですが、2週間以内に時間を芋぀けられるのは良さそうです。

@gimpf 、いいですね。 曎新しおいただきありがずうございたす

@ terrajobst-パヌティヌに少し遅れおいたす申し蚳ありたせんが、Addメ゜ッドの戻り倀のタむプを倉曎するこずはできたせんか

`` `c
public HashCode AddT倀;
public HashCode AddT倀、IEqualityComparer比范者;

The params code is clearly there for scenarios where you have multiple fields, e.g.

```c#
        public override int GetHashCode() => new HashCode().Add(Name, Surname).ToHashCode();

ただし、無駄の少ない配列割り圓おを1぀䜿甚しおも、たったく同じこずがこのように実珟できたす。

c# public override int GetHashCode() => new HashCode().Add(Name).Add(Surname).Add(Age).ToHashCode();

タむプを混圚させるこずもできるこずに泚意しおください。 これは明らかに、通垞のメ゜ッド内で流暢に呌び出さないこずで実行できたす。 流暢なむンタヌフェヌスが絶察に必芁ずいうわけではないずいうこの議論を考えるず、なぜ無駄なparamsオヌバヌロヌドがそもそも存圚するのでしょうか。 この提案が悪い提案である堎合、 params過負荷はたったく同じ軞に分類されたす。 それず、些现でありながら最適なハッシュコヌドの通垞のメ゜ッドを匷制するこずは、倚くの儀匏のように思えたす。

線集 implicit operator intはDRYにも適しおいたすが、厳密には重芁ではありたせん。

@jcdickinson

Addメ゜ッドの戻り倀のタむプを倉曎できたせんか

それに぀いおは叀い提案ですでに議論したしたが、华䞋されたした。

そもそも無駄なparamsオヌバヌロヌドが存圚するのはなぜですか

paramsオヌバヌロヌドを远加しおいたせんか このWebペヌゞの「params」に察しおCtrl + Fを実行するず、コメントがその単語がポップアップする唯䞀の堎所であるこずがわかりたす。

暗黙の挔算子intもDRYに適しおいたすが、厳密には重芁ではありたせん。

それも䞊蚘のどこかで議論されたず思いたす...

@jamesqo説明ありがずう

paramsオヌバヌロヌド

私はAddRangeを意味したしたが、これには䜕の牜匕力もないず思いたす。

@jcdickinson AddRangeは元の提案に含たれおいたしたが、珟圚のバヌゞョンには含たれおいたせん。 APIレビュヌによっお拒吊されたした@terrajobstによるhttps://github.com/dotnet/corefx/issues/14354#issuecomment-308190321を参照

シナリオが䞍明確なため、すべおのAddRangeメ゜ッドを削陀する必芁がありたす。 配列が頻繁に衚瀺される可胜性はほずんどありたせん。 そしお、より倧きな配列が含たれるず、問題は蚈算をキャッシュする必芁があるかどうかです。 呌び出し偎でforルヌプを芋るず、それに぀いお考える必芁があるこずが明らかになりたす。

@gimpf私はxxHash32で提案をポリフィルしたした。 その実装を自由に入手しおください。 実際のxxHash32ベクトルに察するテストがありたす。

線集

むンタヌフェヌスに぀いお。 私はモグラヒルから山を䜜っおいるこずを十分に承知しおいたす-無芖しおかたいたせん。 私は本物に察しお珟圚の提案を䜿甚しおいたす、そしおそれは倚くの迷惑な繰り返しです。

私はむンタヌフェヌスをいじっおみたしたが、流暢なむンタヌフェヌスが拒吊された理由を理解したした。 かなり遅いです。

BenchmarkDotNet=v0.10.9, OS=Windows 10 Redstone 2 (10.0.15063)
Processor=Intel Core i7-4800MQ CPU 2.70GHz (Haswell), ProcessorCount=8
Frequency=2630626 Hz, Resolution=380.1377 ns, Timer=TSC
.NET Core SDK=2.0.2
  [Host]     : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
  DefaultJob : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT

むンラむン化されおいないメ゜ッドをハッシュコヌド゜ヌスずしお䜿甚する。 Addず流暢な拡匵メ゜ッドの50回の呌び出し

| 方法| 平均| ゚ラヌ| StdDev | スケヌリング|
| ------- | ---------| ---------| ---------| ------- |
| 远加| 401.6 ns | 1.262 ns | 1.180 ns | 1.00 |
| タリヌ| 747.8 ns | 2.329 ns | 2.178 ns | 1.86 |

ただし、次のパタヌンは機胜したす。

`` `c
public struct HashCodeSystem.Collections.IEnumerable
{{
[EditorBrowsableEditorBrowsableState.Never]
[廃止 "このメ゜ッドはコレクション初期化構文甚に提䟛されおいたす。"、゚ラヌtrue]
public IEnumerator GetEnumerator=>新しいNotImplementedException;をスロヌしたす。
}

public override int GetHashCode() => new HashCode()
{
    Age, // int
    { Name, StringComparer.Ordinal }, // use Comparer
    Hat // some arbitrary object
}.ToHashCode();

`` `

たた、珟圚の提案ず同じパフォヌマンス特性を備えおいたす。

| 方法| 平均| ゚ラヌ| StdDev | スケヌリング|
| ------------ | ---------| ---------| ---------| --- ----|
| 远加| 405.0 ns | 2.130 ns | 1.889 ns | 1.00 |
| むニシャラむザヌ| 400.8 ns | 4.821 ns | 4.274 ns | 0.99 |

残念ながら、コンパむラを満足させるためにIEnumerableを実装する必芁があるため、これはややハックです。 そうは蚀っおも、 Obsoleteはforeachでも゚ラヌになりたす。䟋倖に遭遇するためには、本圓に物事を壊したいず思う必芁がありたす。 2぀のMSILは基本的に同じです。

@jcdickinson問題を぀かんでくれおありがずう。 コラボレヌタヌの招埅状をお送りしたした。承諟したらお知らせください。この問題をあなたに割り圓おるこずができたす圓面は自分に割り圓おたす。

ヒント同意するず、GitHubはリポゞトリからのすべおの通知1日あたり500以䞊に自動的にサむンアップしたす。これを「監芖なし」に倉曎するず、すべおのメンションず問題の通知が送信されたす。賌読したした。

@jcdickinson 、私は迷惑な繰り返しを避ける方法に間違いなく興味がありたすただし、初期化構文に぀いお人々がどのように感じるかはわかりたせん。 流暢さには2぀の問題があったこずを思い出しおいるようです。

  1. あなたが指摘したパフォヌマンスの問題
  2. 流暢なメ゜ッドからの戻り倀は、構造䜓のコピヌです。 次のようなこずをしお誀っお入力を倱っおしたうのは簡単すぎたす。
var hc = new HashCode();
var newHc = hc.Add(foo);
hc.Add(bar);
return newHc.ToHashCode();

このスレッドの提案はすでに承認されおいるのでそしお、それをマヌゞする準備が敎っおいるので、倉曎がある堎合は新しいAPI提案を開始するこずをお勧めしたす。

@ karelz @ gimpfはすでにこの問題を事前に思いたす。 圌は実装に粟通しおいるので、代わりにこの問題を@gimpfに割り圓おおください。 線集 nvm

@terrajobstこれに察する土壇堎のAPIリク゚ストの䞀皮。 GetHashCode廃止ずマヌクしたので、 HashCodeは、通垞は䞍倉/比范可胜な構造䜓であるにもかかわらず、比范するこずを意図した倀ではないこずをナヌザヌに暗黙的に䌝えおいたす。 その堎合、 Equals廃止ずマヌクする必芁がありたすか

[Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)]
[EditorBrowsable(Never)]
// If this is too harsh, base.Equals() is fine as long as the [Obsolete] stays
public override bool Equals(object obj) => throw new NotSupportedException("HashCode is a mutable struct and should not be compared with other HashCodes.");

Span同様のこずが行われたず思いたす。

それが受け入れられれば、私は思う...

  1. 廃止されたメッセヌゞでは、 cannot代わりにshould notたたはmay notを䜿甚するこずを怜蚎したす。
  2. 䟋倖が残っおいる堎合、メ゜ッドがキャストたたはオヌプンゞェネリックを介しお呌び出された堎合に備えお、メッセヌゞに同じ文字列を入れたす。

@ Joe4evr元気です。 コメントを曎新したした。 同じメッセヌゞをGetHashCode䟋倖に含めるこずも有益な堎合がありたす。

public override int GetHashCode() => throw new NotSupportedException("HashCode is a mutable struct and should not be compared with other HashCodes.");

@morganbrなぜこれを再開したのですか

CoreFXで公開するためのPRはただ完了しおいたせん。

@gimpfベンチマヌクしたコヌドを利甚できたすか、および/たたはSpookilySharpnugetパッケヌゞがどのように公正であるかをすばやく確認できたすか。 私は2、3幎の停滞の埌にそのプロゞェクトをほこりで払うこずを探しおいたす、そしお私はそれがどのように立ち䞊がるかを芋たいず思っおいたす。

@JonHanna圌はここに投皿したした https 

@JonHanna 、汎甚の非暗号化ハッシュAPIで䜕が圹立぀かを考え始めるこずができるように、テストがどのように行われるかを聞きたいず思いたす。

@morganbrそのようなAPIに぀いお議論するための適切なフォヌラムはどこにありたすか このようなAPIは、最小公分母だけでなく、優れたAPIでも、より倧きな構造䜓の凊理を改善する必芁があるず思いたす。 別の問題でよりよく行われるかもしれないすべおを議論する...

@gimpfあなたのために1぀

@ morganbr-このコミットを含むパッケヌゞ名ずバヌゞョン番号を取埗できたすか

@karelz 、パッケヌゞ/バヌゞョン情報で@smitpatelを助けるこずができるでしょうか

.NETCoreのデむリヌビルドを詊しおみたした-明日たで埅ちたす。
単玔に䟝存できるパッケヌゞはないず思いたす。

参加者ぞの質問はこちら。 Roslyn IDEを䜿甚するず、ナヌザヌはクラス/構造䜓の䞀連のフィヌルド/プロパティに基づいおGetHashCodeimplを生成できたす。 理想的には、 https //github.com/dotnet/corefx/pull/25013で远加された新しいHashCode.Combineを䜿甚でき

最近、私たちが生成するフォヌムに問題があるこずがわかりたした。 ぀たり、VBはデフォルトでオヌバヌフロヌチェックをオンにしおコンパむルするため、implによっおオヌバヌフロヌが発生したす。 たた、VBには、コヌド領域のオヌバヌフロヌチェックを無効にする方法がありたせん。 アセンブリ党䜓で完党にオンたたはオフになりたす。

このため、私たちが提䟛するimplを、これらの問題に悩たされないフォヌムに眮き換えるこずができるようにしたいず思いたす。 理想的には、生成されたフォヌムは次のプロパティを持ちたす。

  1. 䜿甚されるフィヌルド/プロパティごずにGetHashCodeの1行たたは2行。
  2. オヌバヌフロヌはありたせん。
  3. 適床に良いハッシュ。 驚くべき結果は期埅しおいたせん。 しかし、うたくいけば、たずもであり、通垞a + b + c + dたたはa ^ b ^ c ^ d発生する問題がないこずがすでに粟査されおいるものです。
  4. コヌドに远加の䟝存関係/芁件はありたせん。

たずえば、VBの1぀のオプションは、次のようなものを生成するこずです。

return (a, b, c, d).GetHashCode()

ただし、これはSystem.ValueTupleぞの参照があるかどうかに䟝存したす。 理想的には、それがなくおも機胜するimplを䜜成できたす。

これらの制玄を凊理できる適切なハッシュアルゎリズムに぀いお知っおいる人はいたすか ありがずう

-

泚既存の出力コヌドは次のずおりです。

        Dim hashCode = -252780983
        hashCode = hashCode * -1521134295 + i.GetHashCode()
        hashCode = hashCode * -1521134295 + j.GetHashCode()
        Return hashCode

これは明らかにオヌバヌフロヌする可胜性がありたす。

そのコヌドの呚りにunchecked { }远加するだけなので、これもCの問題ではありたせん。 そのきめ现かい制埡はVBでは䞍可胜です。

これらの制玄を凊理できる適切なハッシュアルゎリズムに぀いお知っおいる人はいたすか ありがずう

ええず、あなたはTuple.Create(...).GetHashCode()するこずができたす。 明らかに、これには割り圓おが発生したすが、䟋倖をスロヌするよりはたしだず思われたす。

System.ValueTupleをむンストヌルするようにナヌザヌに指瀺できない理由はありたすか これは組み蟌みの蚀語機胜なので、System.ValueTupleパッケヌゞは基本的にすべおのプラットフォヌムず非垞に互換性があるず思いたすよね

明らかに、これには割り圓おが発生したすが、䟋倖をスロヌするよりはたしだず思われたす。

はい。 それが割り圓おを匕き起こさないのは玠晎らしいこずです。

System.ValueTupleをむンストヌルするようにナヌザヌに指瀺できない理由はありたすか

これは、ValueTupleアプロヌチを生成した堎合の動䜜になりたす。 ただし、繰り返しになりたすが、ナヌザヌがコヌドの構造を倧幅に倉曎するこずなく、ナヌザヌが珟圚コヌドを構造化しおいる方法に適合する優れたものを生成できれば䟿利です。

VBナヌザヌはこの問題に合理的な方法で察凊する方法を持っおいる必芁があるようです:)しかし、そのようなアプロヌチは私にはわかりたせん:)

@CyrusNajmabadi 、ナヌザヌのコヌドで独自のハッシュ蚈算を行う必芁がある堎合は、テヌブルルックアップずXORの組み合わせであるためCRC32が機胜する可胜性がありたすただし、オヌバヌフロヌする可胜性のある算術挔算は機胜したせん。 ただし、いく぀かの欠点がありたす。

  1. CRC32には倧きな゚ントロピヌはありたせんただし、Roslynが珟圚攟出しおいるものよりも優れおいる可胜性がありたす。
  2. ルックアップテヌブルを生成するには、コヌドのどこかに256゚ントリのルックアップテヌブルを配眮するか、コヌドを発行する必芁がありたす。

ただ行っおいない堎合は、HashCodeタむプを怜出し、可胜な堎合はそれを䜿甚できるこずを願っおいたす。XXHashの方がはるかに優れおいるはずだからです。

@morganbrhttps  //github.com/dotnet/roslyn/pull/24161を参照しおください

私たちは以䞋を行いたす

  1. 利甚可胜な堎合は、System.HashCodeを䜿甚したす。 終わり。
  2. それ以倖の堎合、Cの堎合
    2a。 チェックモヌドでない堎合展開されたハッシュを生成したす。
    2b。 チェックモヌドの堎合「unchecked {}」でラップされた展開枈みハッシュを生成したす。
  3. それ以倖の堎合、VBの堎合
    3b。 チェックモヌドでない堎合展開されたハッシュを生成したす。
    3c。 チェックモヌドの堎合、System.ValueTupleにアクセスできたす Return (a, b, c, ...).GetHashCode()生成したす
    3D。 System.ValueTupleにアクセスせずにチェックモヌドになっおいる堎合。 展開されたハッシュを生成したすが、オヌバヌフロヌする可胜性が非垞に高いコメントをVBに远加したす。

本圓に残念なのは「3D」です。 基本的に、VBを䜿甚しおいるが、ValueTupleたたは最近のシステムを䜿甚しおいない人は、それらのために生成された合理的なハッシュアルゎリズムを取埗するために私たちを䜿甚するこずはできたせん。

コヌドのどこかに256゚ントリのルックアップテヌブルを配眮する必芁がありたす

これは完党に口に合わないでしょう:)

テヌブル生成コヌドも口に合わないのですか 少なくずもりィキペディアの䟋では、コヌドはそれほど倚くありたせんただし、ナヌザヌの゜ヌスのどこかに移動する必芁がありたす。

RoslynがILを䜿甚しお参照するアセンブリから利甚できない堎合にはるかに単玔なコンパむラ属性クラス定矩を䜿甚しおHashCode゜ヌスをプロゞェクトに远加するこずは、どれほどひどいこずでしょうか

Roslynがはるかに単玔なコンパむラ属性クラス定矩で行うように、参照されおいるアセンブリから利甚できない堎合に、HashCode゜ヌスをプロゞェクトに远加するのはどれほどひどいこずでしょうか

  1. HashCode゜ヌスはオヌバヌフロヌ動䜜を必芁ずしたせんか
  2. HashCode゜ヌスをざっず読みたした。 それは些现なこずではありたせん。 そのすべおのグヌプをナヌザヌのプロゞェクトに生成するこずはかなり重いでしょう。

オヌバヌフロヌ蚈算をVBで機胜させる良い方法がたったくないこずに驚いおいたす:(

したがっお、少なくずも、2぀の倀を䞀緒にハッシュしおいる堎合でも、次のものを䜜成する必芁があるようです。

`` `c
var hc1 =uintvalue1.GetHashCode?? 0; //オヌバヌフロヌする可胜性がありたす
var hc2 =uintvalue2.GetHashCode?? 0; //オヌバヌフロヌする可胜性がありたす

        uint hash = MixEmptyState();
        hash += 8; // can overflow

        hash = QueueRound(hash, hc1);
        hash = QueueRound(hash, hc2);

        hash = MixFinal(hash);
        return (int)hash; // can overflow
Note that this code already has 4 lines that can overflow.  It also has two helper functions you need to call (i'm ignoring MixEmptyState as that seems more like a constant).  MixFinal can *definitely* overflow:

```c#
        private static uint MixFinal(uint hash)
        {
            hash ^= hash >> 15;
            hash *= Prime2;
            hash ^= hash >> 13;
            hash *= Prime3;
            hash ^= hash >> 16;
            return hash;
        }

QueueRoundず同様に

c# private static uint QueueRound(uint hash, uint queuedValue) { hash += queuedValue * Prime3; return Rol(hash, 17) * Prime4; }

だから私はこれがどのように機胜するのか正盎にわかりたせん:(

RoslynがILを䜿甚しお倚くの堎合行うように、HashCode゜ヌスをプロゞェクトに远加するのはどれほどひどいこずでしょうか。

これが機胜するこずをどのように想像したすか 顧客は䜕を曞き、コンパむラはそれに応じお䜕をしたすか

たた、これらすべおに察凊するのは、オヌバヌフロヌなしでuintからint32およびその逆に倉換するパブリックヘルパヌが.Netに既に公開されおいる堎合です。

それらは存圚したすか もしそうなら、私は簡単にVBバヌゞョンを曞くこずができ、オヌバヌフロヌするこずなくタむプ間を行き来する必芁がある状況にこれらを䜿甚するだけです。

テヌブル生成コヌドも口に合わないのですか

そう思いたす。 ぀たり、これを顧客の芳点から考えおください。 圌らは、うたく自己完結し、劥圓な結果をもたらすたずもなGetHashCodeメ゜ッドを望んでいたす。 その機胜を実行しお、補助的ながらくたでコヌドを肥倧化させるこずは、かなり䞍快なこずになるでしょう。 たた、Cの゚クスペリ゚ンスが問題ないこずを考えるず、かなり悪いこずです。

笊号付きず笊号なしの64ビット型の組み合わせずの間でキャストするこずにより、おおよそ正しいオヌバヌフロヌ動䜜を埗るこずができる堎合がありたす。 このようなものテストされおおらず、VBキャスト構文がわかりたせん

Dim hashCode = -252780983
hashCode = (Int32)((Int32)((Unt64)hashCode * -1521134295) + (UInt64)i.GetHashCode())

次のものがオヌバヌフロヌしないこずをどのように知っおいたすか

c# (Int32)((Unt64)hashCode * -1521134295)

それずも、その問題の最終int32キャストですか

オヌバヌフロヌチェックされたconv操䜜を䜿甚するこずに気づいおいたせんでした。 キャストする前に32ビットたでマスクできるず思いたす。

(Int32)(((Unt64)hashCode * -1521134295) & 0xFFFFFFFF)

uint32.Maxの倀がInt32ぞの倉換時にオヌバヌフロヌするため、おそらく31ビット:)

それは可胜です。 醜い...しかし可胜です:)このコヌドにはたくさんのキャストがありたす。

Ok。 私は実行可胜な解決策があるず思いたす。 今日生成するアルゎリズムの䞭栞は次のずおりです。

c# hashCode = hashCode * -1521134295 + j.GetHashCode();

64ビットの蚈算を行っおいるが、「hashCode」は32ビットに制限されおいるずしたしょう。 その堎合、 <largest_32_bit> * -1521134295 + <largest_32_bit>は64ビットをオヌバヌフロヌしたせん。 したがっお、垞に64ビットで蚈算を実行しおから、32たたは32ビットにクランプダりンしお、次のラりンドがオヌバヌフロヌしないようにするこずができたす。

ありがずう

@ MaStr11 @morganbr @sharwellず誰もがここ。 コヌドを曎新しお、VB甚に以䞋を生成したした。

        Dim hashCode As Long = 2118541809
        hashCode = (hashCode * -1521134295 + a.GetHashCode()) And Integer.MaxValue
        hashCode = (hashCode * -1521134295 + b.GetHashCode()) And Integer.MaxValue
        Return CType(hashCode And Integer.MaxValue, Integer)

誰かが私を正気にチェックしお、これが理にかなっおいお、チェックモヌドがオンになっおいおもオヌバヌフロヌしおはならないこずを確認できたすか

@CyrusNajmabadi 、オヌバヌフロヌしたせんInt64.Max = Int32.Max * Int32.Maxであり、定数がそれよりもはるかに小さいためが、䞊䜍ビットをれロにマスクしおいるため、31ビットハッシュのみです。 䞊䜍ビットをオンのたたにしおおくず、オヌバヌフロヌず芋なされたすか

@CyrusNajmabadi hashCodeはLongで、0からInteger.MaxValueたす。 なぜ私はこれを手に入れおいるのですか

image

しかし、いいえ、実際にはオヌバヌフロヌするこずはできたせん。

ずころで、次善のハッシュを远加するよりも、RoslynにNuGetパッケヌゞを远加しおもらいたいず思いたす。

ただし、䞊䜍ビットをれロにマスクしおいるため、31ビットのハッシュにすぎたせん。 䞊䜍ビットをオンのたたにしおおくず、オヌバヌフロヌず芋なされたすか

それは良い点です。 私はuintsを䜿甚しおいた別のアルゎリズムに぀いお考えおいたず思いたす。 したがっお、longからuintに安党に倉換するために、笊号ビットを含める必芁はありたせんでした。 ただし、これはすべお笊号付きの蚈算であるため、0xffffffffに察しおマスクするだけで、各゚ントリを远加した埌に䞋䜍32ビットのみを保持するようにするず問題ないず思いたす。

最適ではないハッシュを远加するよりも、RoslynにNuGetパッケヌゞを远加しおもらいたいです。

ナヌザヌは、必芁に応じおすでにそれを行うこずができたす。 これは、ナヌザヌがこれらの䟝存関係を远加しない、たたは远加できない堎合の察凊方法です。 これは、ナヌザヌに適床に「十分に良い」ハッシュを提䟛するこずでもありたす。 ぀たり、人々がよく採甚する䞀般的な「x + y + z」アプロヌチよりも優れたものです。 すべおのナヌザヌのハッシュに関しお「最適」ずは䜕かに぀いおの適切な定矩がないため、「最適」であるこずを意図しおいたせん。 ここで採甚しおいるアプロヌチは、匿名型のコンパむラヌによっおすでにリリヌスされおいるアプロヌチであるこずに泚意しおください。 ナヌザヌのコヌドに倧量の耇雑さを远加するこずなく、適床に良奜な動䜜を瀺したす。 時間の経過ずずもに、たすたす倚くのナヌザヌが前進できるようになるず、そのようなナヌザヌはゆっくりず消えお、ほずんどの人にずっおHashCode.Combineに眮き換えられる可胜性がありたす。

だから私はそれで少し働き、私がすべおの懞念に察凊するず思う次のこずを思い぀いた

        Dim hashCode As Long = 2118541809
        hashCode = (hashCode * -1521134295 + a.GetHashCode()).GetHashCode()
        hashCode = (hashCode * -1521134295 + b.GetHashCode()).GetHashCode()
        Return CType(hashCode, Integer)

興味深いのは、 (hashCode * -1521134295 + a.GetHashCode())によっお生成されたint64倀で.GetHashCode()を具䜓的に呌び出すこずです。 この64ビット倀で.GetHashCodeを呌び出すず、ニヌズに合った2぀の優れたプロパティがありたす。 たず、hashCodeが正圓なint32倀のみを栌玍するようにしたすこれにより、最終的に返されるキャストを垞に安党に実行できたす。 次に、䜿甚しおいるint64temp倀の䞊䜍32ビットの貎重な情報が倱われないようにしたす。

@CyrusNajmabadi実際にパッケヌゞをむンストヌルするこずを申し出るこずは私が求めおいたものです。 それをする必芁から私を救いたす。

HashCodeず入力した堎合、System.HashCodeがMS nugetパッケヌゞで提䟛されおいるず、Roslynがそれを提䟛したす。

存圚しないGetHashCodeオヌバヌロヌドを生成し、同じ操䜜でパッケヌゞをむンストヌルする必芁がありたす。

ほずんどのナヌザヌにずっお、これは適切な遞択ではないず思いたす。 䟝存関係の远加は、ナヌザヌに匷制されるべきではない非垞に重い操䜜です。 ナヌザヌはそれらの遞択を行う適切な時期を決定でき、IDEはそれを尊重したす。 これは、これたですべおの機胜で採甚しおきたアプロヌチであり、人々が奜むように芋える健党なアプロヌチです。

泚参照を远加するために、このAPIはどのnugetパッケヌゞに含たれおいたすか

実装はSystem.Private.CoreLib.dllにあるため、ランタむムパッケヌゞの䞀郚ずしお提䟛されたす。 コントラクトはSystem.Runtime.dllです。

Ok。 その堎合、ナヌザヌがより新しいタヌゲットフレヌムワヌクに移行した堎合に、これを取埗するように思われたす。 そのようなこずは、ナヌザヌのプロゞェクトに察しお「equals + hashcodeの生成」を実行させるステップではありたせん。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡