Runtime: ์ œ์•ˆ: ์ข‹์€ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก System.HashCode๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2016๋…„ 12์›” 09์ผ  ยท  182์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: dotnet/runtime

์—…๋ฐ์ดํŠธ 6/16/17: ์ž์› ๋ด‰์‚ฌ์ž๋ฅผ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค

API ๋ชจ์–‘์ด ์™„์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ๊ตฌํ˜„์— ์‚ฌ์šฉํ•  ํ›„๋ณด ๋ชฉ๋ก ์ค‘์—์„œ ๊ฐ€์žฅ ์ข‹์€ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ฒฐ์ •ํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๊ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ฒ˜๋ฆฌ๋Ÿ‰/๋ถ„ํฌ๋ฅผ ์ธก์ •ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค„ ์‚ฌ๋žŒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์— ๋Œ“๊ธ€์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”.

์—…๋ฐ์ดํŠธ 6/13/17: ์ œ์•ˆ ์ˆ˜๋ฝ!

https://github.com/dotnet/corefx/issues/14354#issuecomment -308190321์—์„œ @terrajobst ๊ฐ€ ์Šน์ธํ•œ API๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

// 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();
    }
}

๋น„๊ณ 

์ด API์˜ ๋ชฉํ‘œ๋Š” https://github.com/dotnet/corefx/issues/14354#issuecomment -305019329์—์„œ @terrajobst ์˜ ์˜๊ฒฌ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค . ๊ทธ์˜ ๋ง์€ ๋ชจ๋‘ ์œ ํšจํ•˜๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ €๋Š” ํŠนํžˆ ๋‹ค์Œ์„ ์ง€์ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

  • API ๋Š” ๊ฐ•๋ ฅํ•œ ์•”ํ˜ธํ™” ํ•ด์‹œ๋ฅผ ์ƒ์„ฑ
  • API๋Š” "a" ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ํŠน์ • ํ•ด์‹œ ์ฝ”๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ณด์žฅํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‚˜์ค‘์— ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜์—์„œ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • API๋Š” ์ฃผ์–ด์ง„ ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ ๋™์ผํ•œ ๊ฐ’์ด ๋™์ผํ•œ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๋™์ผํ•œ ์•ฑ์˜ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋Š” ๋ฌด์ž‘์œ„ํ™”๋กœ ์ธํ•ด ๋‹ค๋ฅธ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์†Œ๋น„์ž๊ฐ€ ํ•ด์‹œ ๊ฐ’์„ ์œ ์ง€ํ•˜๊ณ  ์‹ค์ˆ˜๋กœ ์‹คํ–‰(๋˜๋Š” ๋” ๋‚˜์œ ๊ฒฝ์šฐ ํ”Œ๋žซํผ ๋ฒ„์ „)์—์„œ ์•ˆ์ •์ ์ธ ๊ฒƒ์— ์˜์กดํ•˜์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
api-approved area-System.Numerics up-for-grabs

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๊ฒฐ์ •

  • ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ๋ถˆ๋ถ„๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  AddRange ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด์€ ๋งค์šฐ ์ž์ฃผ ๋‚˜ํƒ€๋‚  ๊ฐ€๋Šฅ์„ฑ์ด ๋‹ค์†Œ ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ผ๋‹จ ๋” ํฐ ๋ฐฐ์—ด์ด ๊ด€๋ จ๋˜๋ฉด ๋ฌธ์ œ๋Š” ๊ณ„์‚ฐ์„ ์บ์‹œํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ํ˜ธ์ถœ ์ธก์—์„œ for ๋ฃจํ”„๋ฅผ ๋ณด๋ฉด ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์žˆ์Œ์„ ๋ถ„๋ช…ํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ํ• ๋‹น๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— IEnumerable ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ AddRange ์— ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • string ์™€ StringComparison ๊ฐ€ ๊ฑธ๋ฆฌ๋Š” string Add ๋Œ€ํ•œ ์˜ค๋ฒ„๋กœ๋“œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ, IEqualityComparer ํ†ตํ•ด ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋‚˜์ค‘์— ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • GetHashCode ๋ฅผ ์˜ค๋ฅ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ์ƒ๊ฐ์ด์ง€๋งŒ ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€ IntelliSense์—์„œ ์ˆจ๊ธธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ๋‹ค์Œ์„ ๋‚จ๊น๋‹ˆ๋‹ค.

```C#
// ์ฝ”์–ด ์–ด์…ˆ๋ธ”๋ฆฌ์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
// .NET ํ”„๋ ˆ์ž„์›Œํฌ: mscorlib
// .NET ์ฝ”์–ด : System.Runtime / System.Private.CoreLib
๋„ค์ž„์ŠคํŽ˜์ด์Šค ์‹œ์Šคํ…œ
{
๊ณต๊ฐœ ๊ตฌ์กฐ์ฒด ํ•ด์‹œ ์ฝ”๋“œ
{
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5, T6 ๊ฐ’6);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5, T6 ๊ฐ’6, T7 ๊ฐ’7);
public static int ๊ฒฐํ•ฉ(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๋Š” ๋” ๋น ๋ฅด์ง€๋งŒ ์ž ์žฌ์ ์œผ๋กœ ๋ถ„์‚ฐ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋˜๋Š” ์‹ค์ œ๋กœ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๊ฐ€ ๋ฌด์—‡์ด๋“ ).

๊ทธ๋Š” ํ•ด์‹œ ์‹œ๋“œ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ์ง€์ •ํ•˜๊ธฐ๋ฅผ ์›ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด์‹œ๊ฐ€ ๊ฒฐ์ •์ ์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์œ ์šฉํ•œ ๋™์ž‘์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ์ด๊ฒƒ์„ ํ†ต์ œํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋งˆ๋„ Hash๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ์‹œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ (๊ทธ๋ฆฌ๊ณ  ์ž„์˜์˜ ์‹œ๋“œ๋ฅผ ์‚ฌ์šฉํ•จ) ์‹œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋„๋ก ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ : 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.Whatever API๊ฐ€ ์žˆ์œผ๋ฉด ๊ธฐ์  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”!

MurmurHash๋Š” ์–ด๋–ป์Šต๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๋น ๋ฅด๋ฉฐ ๋งค์šฐ ์ข‹์€ ํ•ด์‹ฑ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ 32๋น„ํŠธ ํ•ด์‹œ๋ฅผ ๋‚ด๋ณด๋‚ด๋Š” ๊ตฌํ˜„๊ณผ 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%์˜ ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ์ถฉ๋ถ„ํžˆ ์ข‹์€ ์†”๋ฃจ์…˜์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ง€๊ธˆ์€ ์•„๋ฌด๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค... :-/

ํ•ด์‹œ์ฝ”๋“œ = ํ•ด์‹œ์ฝ”๋“œ * -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๋ฅผ ์ฐจ๋‹จํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค API๊ฐ€ ๋ฆด๋ฆฌ์Šค๋œ ํ›„ 32๋น„ํŠธ ๊ตฌ์กฐ์ฒด ๋ณต์‚ฌ๋ณธ์„ ์ตœ์ ํ™”ํ•˜๋„๋ก JIT ํŒ€์— ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๊นŒ? ์‚ฌ๋ณธ?

95%์˜ ๊ฒฝ์šฐ์— ์ถฉ๋ถ„ํžˆ ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฐ„๋‹จํ•œ 32๋น„ํŠธ ๋ˆ„์  ํ•ด์‹œ๋ฅผ ์ƒ๊ฐํ•ด๋‚ผ ์ˆ˜ ์—†์Šต๋‹ˆ๊นŒ?

์šฐ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฌธ์ž์—ด์— ๋Œ€ํ•œ 32๋น„ํŠธ ๋ˆ„์  ํ•ด์‹œ๋ฅผ ์‹ฌํ•˜๊ฒŒ ํƒœ์›Œ ์™”์œผ๋ฉฐ ์ด๊ฒƒ์ด .NET Core์˜ ๋ฌธ์ž์—ด์— ๋Œ€ํ•œ Marvin ํ•ด์‹œ - https://github.com/dotnet/corert/blob/87e58839d6629b5f90777f886a2f52d7a99c076f/s src/System/Marvin.cs#L25. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์—ฌ๊ธฐ์„œ ๊ฐ™์€ ์‹ค์ˆ˜๋ฅผ ๋ฐ˜๋ณตํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@jkotas , ์„ฑ๋Šฅ์ด ์ด ์œ ํ˜•์— ์ •๋ง ์ค‘์š”ํ•ฉ๋‹ˆ๊นŒ?

์„ฑ๋Šฅ์ด ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด API๊ฐ€ ์ž๋™ ์ƒ์„ฑ ์ปดํŒŒ์ผ๋Ÿฌ ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ๋  ๊ฒƒ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์ด๋Š” ๊ฒƒ๋ณด๋‹ค ์ƒ์„ฑ๋œ ๋” ์ž‘์€ ์ฝ”๋“œ๋ฅผ ์„ ํ˜ธํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ ์ฐฝํ•˜์ง€ ์•Š์€ ํŒจํ„ด์€ ๋” ์ž‘์€ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฌธ์ž์—ด์— ๋Œ€ํ•œ 32๋น„ํŠธ ๋ˆ„์  ํ•ด์‹œ๋กœ ์ธํ•ด ์‹ฌํ•˜๊ฒŒ ํ™”์ƒ์„ ์ž…์—ˆ์Šต๋‹ˆ๋‹ค.

95%์˜ ๊ฒฝ์šฐ๋Š” ์•„๋‹Œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์˜ค๋Š˜๋‚  ์ˆ˜๋™์œผ๋กœ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  ์œ ํ˜•์— ๋Œ€ํ•ด "์ถฉ๋ถ„ํžˆ ์ข‹์€" ํ•ด์‹œ๋ฅผ ์›ํ•˜๋Š” ์ผ๋ฐ˜ ๊ฐœ๋ฐœ์ž์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด API๊ฐ€ ์ž๋™ ์ƒ์„ฑ ์ปดํŒŒ์ผ๋Ÿฌ ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ๋  ๊ฒƒ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์ด๋Š” ๊ฒƒ๋ณด๋‹ค ์ƒ์„ฑ๋œ ๋” ์ž‘์€ ์ฝ”๋“œ๋ฅผ ์„ ํ˜ธํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์œ ์ฐฝํ•˜์ง€ ์•Š์€ ํŒจํ„ด์€ ๋” ์ž‘์€ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ Roslyn ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ์œ ํ˜•์— ๋Œ€ํ•ด GetHashCode๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ๋„์šธ ๋•Œ Roslyn IDE์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๊ณ  ์œ ์ง€ํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ์ด๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค.

```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 ์›น ์„œ๋ฒ„๋Š” ์ˆ˜์‹ ๋œ ๋‚ด์šฉ์„ ํ•ด์‹œ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— DoS ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ฐœ๊ฒฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ "์ถฉ๋ถ„ํžˆ ์ข‹์€" ํ•ด์‹œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜์œ ๋ณด์•ˆ ๋ฌธ์ œ๋กœ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์ด ํŠœํ”Œ์— ์ถฉ๋ถ„ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋“œ์‹œ ์•„๋‹™๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•˜๋Š” ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํŠœํ”Œ์— ๋Œ€ํ•œ ๋ฐฑ์Šคํ†ฑ ์กฐ์น˜๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

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

์ด๊ฒƒ์€ ๋‚˜์—๊ฒŒ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹น์‹ ์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€๋ฅผ ๋ง์”€ํ•˜์‹œ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์›๋ž˜ ๋ฌธ์ž์—ด ํ•ด์‹œ๋Š” ์ผ๋ฐ˜ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ž˜ ์ž‘๋™ํ•˜๋Š” "์ถฉ๋ถ„ํžˆ ์ข‹์€" ํ•ด์‹œ์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ASP.NET ์›น ์„œ๋ฒ„๋Š” ์ˆ˜์‹ ๋œ ๋‚ด์šฉ์„ ํ•ด์‹œ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— DoS ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ฐœ๊ฒฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ "์ถฉ๋ถ„ํžˆ ์ข‹์€" ํ•ด์‹œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚˜์œ ๋ณด์•ˆ ๋ฌธ์ œ๋กœ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค.

์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋ณด์•ˆ/DoS ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ข‹์€ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ ์œ ํ˜•์€ 95% ์ด์ƒ์˜ ๊ฒฝ์šฐ์— ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์„ ํƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ž, ๊ทธ๋ ‡๋‹ค๋ฉด 95%์˜ ๊ฒฝ์šฐ์— ์ถฉ๋ถ„ํ•œ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ณด์•ˆ/DoS ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์‚ฌ๋žŒ์€ ํ•ด๋‹น ๋ชฉ์ ์œผ๋กœ ๋ฌธ์„œํ™”๋œ ํŠน์ˆ˜ ์–‘์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋“œ์‹œ ์•„๋‹™๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•˜๋Š” ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํŠœํ”Œ์— ๋Œ€ํ•œ ๋ฐฑ์Šคํ†ฑ ์กฐ์น˜๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

ํ™•์ธ. ์‚ฌ์šฉ์ž ๊ฐ€ ๋™์ผํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

--
"๋ณดํŽธ์ ์ธ ์†”๋ฃจ์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋‘๊ฐ€ ์Šค์Šค๋กœ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค"๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ €๋Š” ์—ฌ๊ธฐ์„œ ์ •๋ง ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ตœ์•…์˜ ์žฅ์†Œ ์ค‘ ํ•˜๋‚˜์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ™•์‹คํžˆ ๋Œ€๋ถ€๋ถ„์˜ ๊ณ ๊ฐ์€ DoS ๋ฌธ์ œ์— ๋Œ€ํ•ด ์ž์ฒด '๋งˆ๋นˆ ํ•ด์‹œ'๋ฅผ ๋กค๋งํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ ๋‹จ์ง€ ํ•˜๋‚˜์˜ ์ตœ์ข… ํ•ด์‹œ๋กœ ํ•„๋“œ ํ•ด์‹œ๋ฅผ ์ถ”๊ฐ€, xoring ๋˜๋Š” ์ž˜๋ชป ๊ฒฐํ•ฉํ–ˆ์„ ๋ฟ์ž…๋‹ˆ๋‹ค.

95%์˜ ๊ฒฝ์šฐ์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ์ข‹์€ enogh ํ•ด์‹œ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 5%์˜ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•œ๋‹ค๋ฉด ๊ทธ์— ๋Œ€ํ•œ ํŠนํ™”๋œ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‚˜์—๊ฒŒ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

์ข‹์Šต๋‹ˆ๋‹ค :) ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋…ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

```c#
๋„ค์ž„์ŠคํŽ˜์ด์Šค System.Numerics.Hashing
{
๋‚ด๋ถ€ ์ •์  ํด๋ž˜์Šค HashHelpers
{
๊ณต๊ฐœ ์ •์  ์ฝ๊ธฐ ์ „์šฉ int RandomSeed = ์ƒˆ๋กœ์šด 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 ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐ

@jkotas ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค :p

๋”ฐ๋ผ์„œ ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ DoS ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•œ ์‹œ์ ์„ ๋ชจ๋ฅธ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. DoS ๊ณต๊ฒฉ์— ๋Œ€ํ•œ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— Marvin32๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฌธ์ž์—ด์„ ์ „ํ™˜ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

'95%์˜ ๊ฒฝ์šฐ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š๋‹ค'๋Š” ์‹์œผ๋กœ ๋งํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค. ์ฆ๋ช…ํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ณ  ์„ฑ๋Šฅ ๋Œ€๊ฐ€๋ฅผ ์น˜๋ฅด๋”๋ผ๋„ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๊ฒƒ์—์„œ ๋ฒ—์–ด๋‚˜๋ ค๋ฉด ํ•ด์‹œ ์ฝ”๋“œ ๊ตฌํ˜„์— "์ด๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค"๋ผ๊ณ  ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ Crypto Board ๊ฒ€ํ† ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ASP.NET ์•ฑ์—๋Š” ๋ณด์•ˆ/DoS ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์ธ. ๊ทธ๋ž˜์„œ ์˜ค๋Š˜๋‚  ์•„๋ฌด๋„ ํ•ด์‹œ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋„์›€์„ ๋ฐ›์ง€ ๋ชปํ•˜์—ฌ ์ผ์„ ์ œ๋Œ€๋กœ ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๋ถ„๋ช…ํžˆ ๊ทธ ์„ธ๊ณ„์˜ ์ƒํƒœ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ์šฉ์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์˜ค๋Š˜๋‚  ์‚ฌ๋žŒ๋“ค์ด ์†์œผ๋กœ ๊ตด๋ฆฌ๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ๋ณด์ด๋Š” ํ•ฉ๋ฆฌ์ ์ธ ํ•ด์‹ฑ ์‹œ์Šคํ…œ์„ ์ œ๊ณตํ•˜๋ฉด ์–ด๋–ค ํ”ผํ•ด๋ฅผ ์ž…๊ฒŒ ๋ ๊นŒ์š”?

์ž…์ฆํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ณ  ์„ฑ๋Šฅ ๋น„์šฉ์ด ์žˆ๋”๋ผ๋„ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‹น์‹ ์ด ๋ฌด์–ธ๊ฐ€๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ๋žŒ๋“ค์€ ๊ณ„์†ํ•ด์„œ ๋‚˜์œ ์ผ์„ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™„๋ฒฝํ•œ ๊ฒƒ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— "์ถฉ๋ถ„ํžˆ ์ข‹์€ ๊ฒƒ"์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๊ฒƒ์€ ์˜ค๋Š˜๋‚  ์šฐ๋ฆฌ๊ฐ€ ๊ฐ€์ง„ ์—ด์•…ํ•œ ํ˜„์ƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ASP.NET ์•ฑ์—๋Š” ๋ณด์•ˆ/DoS ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด๊ฐ€ ์•Œ๊ธฐ๋กœ๋Š” ์ž„์˜์˜ ์ž…๋ ฅ์„ ์ˆ˜๋ฝํ•œ ๋‹ค์Œ ์ž…๋ ฅ์„ ํŠน์ˆ˜ํ•˜๊ฒŒ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๋Š” ์ผ๋ถ€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ DoS ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ข‹์•„, ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์˜จ ์›น ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์–ป๋Š” ๋ฌธ์ž์—ด์— ๋Œ€ํ•œ ์šฐ๋ ค๋ฅผ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋‚˜๋จธ์ง€ ์œ ํ˜•์—๋Š” ์–ด๋–ป๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๊นŒ?

๋‹ค์Œ ์œ ํ˜• ์„ธํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. DoS ์•ˆ์ „ํ•ด์•ผ ํ•˜๋Š” ์‚ฌ์šฉ์ž ์œ ํ˜•. ์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” ๋„์šธ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋ฌด๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ๋žŒ๋“ค์ด ์˜ณ์€ ์ผ์„ ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์ข‹์ง€ ์•Š์€ ์ƒํ™ฉ์— ์ฒ˜ํ•ด ์žˆ์Šต๋‹ˆ๋‹ค.
  2. DoS ์•ˆ์ „์ด ํ•„์š”ํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž ์œ ํ˜•. ์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” ๋„์šธ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋ฌด๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ๋žŒ๋“ค์ด ์˜ณ์€ ์ผ์„ ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์ข‹์ง€ ์•Š์€ ์ƒํ™ฉ์— ์ฒ˜ํ•ด ์žˆ์Šต๋‹ˆ๋‹ค.
  3. DoS ์•ˆ์ „ํ•ด์•ผ ํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ์œ ํ˜•. ์ง€๊ธˆ์€ DoS๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์ง€๋งŒ API๋ฅผ ํ†ตํ•ด ๋…ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  4. DoS ์•ˆ์ „ํ•˜์ง€ ์•Š์•„๋„ ๋˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ์œ ํ˜•. ์ง€๊ธˆ์€ ํ•ด์‹œ๋ฅผ ์ œ๊ณตํ–ˆ์ง€๋งŒ API๋ฅผ ํ†ตํ•ด ๋…ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๊ฐ€ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ '1' ๋˜๋Š” '2'๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•  ๋งŒํผ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” '2'์— ๋Œ€ํ•œ ์†”๋ฃจ์…˜์ด '1'์— ์ข‹์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ๊ฑฑ์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์• ์ดˆ์— ์ œ๊ณต์กฐ์ฐจ ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๊ฐ€ '1'์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์กฐ์ฐจ ์ œ์‹œํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ๋ฏฟ์„ ์ˆ˜ ์—†์„ ์ •๋„๋กœ ์ด์ƒํ•œ ์œ„์น˜์— ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” DoSing๊ณผ ASP์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•˜๊ณ  ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ ์‚ฌ๋žŒ๋“ค์„ ๋„์šธ ๋งŒํผ ๊ฑฑ์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” ๊ทธ ๋ฌธ์ œ๋กœ ์‚ฌ๋žŒ๋“ค์„ ๋•์ง€ ์•Š์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— DoS๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” ๊ธฐ๊บผ์ด ๋„์™€์ค„ ์ƒ๊ฐ๋„ ์—†์Šต๋‹ˆ๋‹ค.

--

์ด ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ์ค‘์š”ํ•˜๋‹ค๋ฉด(์ €๋Š” ๊ธฐ๊บผ์ด ์ˆ˜๋ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค) ๋‘ ๊ฐœ์˜ API๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๋ฌธ์„œํ™”ํ•˜์‹ญ์‹œ์˜ค. ๋ฌด์—‡์„ ์œ„ํ•œ ๊ฒƒ์ธ์ง€ ๋ช…ํ™•ํžˆ ํ•˜์‹ญ์‹œ์˜ค. ์‚ฌ๋žŒ๋“ค์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค . ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ, ๊ทธ๋“ค์€ ์–ด์จŒ๋“  ์˜ค๋Š˜๋‚  ์ œ๋Œ€๋กœ ์ผ์„ ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์œผ๋ฏ€๋กœ ์–ด๋–ป๊ฒŒ ์ƒํ™ฉ์ด ๋” ๋‚˜๋น ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹น์‹ ์€ ๋ฌด์—‡์„ ์ƒ๊ฐํ•ฉ๋‹ˆ๊นŒ

๋‚˜๋Š” ์–ด๋–ค ์‹ ์œผ๋กœ๋“  ์˜๊ฒฌ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ณ ๊ฐ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” API๋กœ ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์„ฑ๋Šฅ๊ณผ ๋ช…ํ™•ํ•œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ๊ฐ„๋‹จํ•œ API๋ฅผ ์ œ๊ณตํ•˜๋Š” API๋ผ๋ฉด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

์ •๋ ฌ๋œ ๋ฐฉ์‹์œผ๋กœ ํ•„๋“œ/์†์„ฑ ์ง‘ํ•ฉ์„ ๊ฒฐํ•ฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์˜ 99%๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์ •์  ํ˜•์‹์ด ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ์œ ํ˜•์— ๊ทธ๋Ÿฐ ๊ฒƒ์„ ์ƒ๋‹นํžˆ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์‹ฌํ”Œํ•œ ์Šคํƒœํ‹ฑ ํ˜•ํƒœ๊ฐ€ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”

๋™์˜ํ•˜๋‹ค.

์ •๋ ฌ๋œ ๋ฐฉ์‹์œผ๋กœ ํ•„๋“œ/์†์„ฑ ์ง‘ํ•ฉ์„ ๊ฒฐํ•ฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์˜ 99%๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์ •์  ํ˜•์‹์ด ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ์œ ํ˜•์— ๊ทธ๋Ÿฐ ๊ฒƒ์„ ์ƒ๋‹นํžˆ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋™์˜ํ•˜๋‹ค.

์ผ์ข…์˜ API๊ฐ€ ๊ตฌํ˜„๋˜๋Š” ๊ฒƒ์„ ์ •๋ง๋กœ ๋ณด๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ์˜ ์ค‘๊ฐ„์—์„œ ๋‘ ๋ถ„์„ ๋ชจ๋‘ ๋งŒ๋‚˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. @jkotas ๋‚˜๋Š” ๋‹น์‹ ์ด ๋ถˆ๋ณ€์˜ ์ธ์Šคํ„ด์Šค ๊ธฐ๋ฐ˜ 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๋ฅผ ์ˆ˜๋ฝํ•˜๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ GetHashCode๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜๋Š” 8๊ฐœ์˜ ์˜ค๋ฒ„๋กœ๋“œ๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ์ค‘์š”ํ•˜๋‹ค๋ฉด(์ €๋Š” ๊ธฐ๊บผ์ด ์ˆ˜๋ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค) ๋‘ ๊ฐœ์˜ API๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๋ฌธ์„œํ™”ํ•˜์‹ญ์‹œ์˜ค. ๋ฌด์—‡์„ ์œ„ํ•œ ๊ฒƒ์ธ์ง€ ๋ช…ํ™•ํžˆ ํ•˜์‹ญ์‹œ์˜ค. ์‚ฌ๋žŒ๋“ค์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ๊ทธ๊ฒƒ์„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ, ๊ทธ๋“ค์€ ์–ด์จŒ๋“  ์˜ค๋Š˜ ์ผ์„ ์ œ๋Œ€๋กœ ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์œผ๋‹ˆ ์–ด๋–ป๊ฒŒ ์ƒํ™ฉ์ด ๋” ๋‚˜๋น ์งˆ๊นŒ์š”?

์‚ฌ๋žŒ๋“ค์€ ๊ทธ๊ณณ์— ์žˆ์„ ๋•Œ ๋ฌผ๊ฑด์„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. XSS. ์ฒ˜์Œ๋ถ€ํ„ฐ ์›น ์–‘์‹์—๋„ HTML ์ธ์ฝ”๋”ฉ ์ถœ๋ ฅ ๊ธฐ๋Šฅ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐœ๋ฐœ์ž๋Š” ์œ„ํ—˜์„ ์•Œ์ง€ ๋ชปํ–ˆ๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชฐ๋ž๊ณ  ๋„ˆ๋ฌด ๋Šฆ์—ˆ์„ ๋•Œ ์•ฑ์ด ๊ฒŒ์‹œ๋˜์—ˆ์œผ๋ฉฐ ์›์Šค, ์ด์ œ ์ธ์ฆ ์ฟ ํ‚ค๊ฐ€ ํ•ด์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋ณด์•ˆ ์„ ํƒ๊ถŒ์„ ์ฃผ๋Š” ๊ฒƒ์€ ๊ทธ๋“ค์ด

  1. ๋ฌธ์ œ์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์œ„ํ—˜์ด ๋ฌด์—‡์ธ์ง€ ์ดํ•ดํ•˜์‹ญ์‹œ์˜ค.
  3. ์ด๋Ÿฌํ•œ ์œ„ํ—˜์„ ํ‰๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. ํ•ด์•ผ ํ•  ์ผ์„ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ฐ€์ •์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋Œ€๋‹ค์ˆ˜์˜ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ๋„ˆ๋ฌด ๋Šฆ์—ˆ์„ ๋•Œ๋งŒ ๋ฌธ์ œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ๋ณด์•ˆ ํšŒ์˜์— ๊ฐ€์ง€ ์•Š๊ณ  ๋ฐฑ์„œ๋ฅผ ์ฝ์ง€ ์•Š์œผ๋ฉฐ ์†”๋ฃจ์…˜์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ASP.NET HashDoS ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์šฐ๋ฆฌ๋Š” ๊ทธ๋“ค์„ ์œ„ํ•ด ์„ ํƒํ–ˆ๊ณ , ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณดํ˜ธํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์˜ณ์€ ์ผ์ด์—ˆ๊ณ  ๊ฐ€์žฅ ํฐ ์˜ํ–ฅ์„ ๋ฏธ์ณค๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ๋ฌธ์ž์—ด์—๋งŒ ์ ์šฉํ–ˆ๊ณ , ์ด๋Š” ์‚ฌ์šฉ์ž ์ž…๋ ฅ์œผ๋กœ ์ปค์Šคํ…€ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ๋‚˜์œ ์œ„์น˜์— ๋‚จ๊ฒจ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์˜ณ์€ ์ผ์„ ํ•ด์•ผ ํ•˜๊ณ , ์ง€๊ธˆ ๊ทธ ๊ณ ๊ฐ์„ ๋ณดํ˜ธํ•˜๋„๋ก ๋•๊ณ , ์‹คํŒจ๊ฐ€ ์•„๋‹Œ ์„ฑ๊ณต์˜ ๊ตฌ๋ฉ์ด๋ฅผ ๊ฐ€์ง€๊ณ  ๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ณด์•ˆ์„ ์œ„ํ•œ API ์„ค๊ณ„๋Š” ๋•Œ๋•Œ๋กœ ์„ ํƒ์ด ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž๊ฐ€ ์•Œ๋“  ๋ชจ๋ฅด๋“  ์‚ฌ์šฉ์ž๋ฅผ ๋•๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ํ•ญ์ƒ ๋ณด์•ˆ์— ์ค‘์ ์„ ๋‘์ง€ ์•Š์€ ํ•ด์‹œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‘ ๊ฐ€์ง€ ์˜ต์…˜์ด ์ฃผ์–ด์กŒ์„ ๋•Œ

  1. ๊ธฐ๋ณธ ํ•ด์‹œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ๋ณด์•ˆ์„ ์ธ์‹ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ๋ณด์•ˆ ์ธ์‹ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๊ธฐ๋ณธ ํ•ด์‹œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ๋ณด์•ˆ์„ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ๋น„๋ณด์•ˆ ์ธ์‹ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๋‘ ๋ฒˆ์งธ๊ฐ€ ๋” ๋‚˜์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ œ์•ˆ๋œ ๊ฒƒ์€ ์ „์ฒด ์•”ํ˜ธํ™” ํ•ด์‹œ์˜ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ๊ฒƒ์€ ์ข‹์€ ํƒ€ํ˜‘์„ ๋งŒ๋“œ๋Š”๊ฐ€?

์ด ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ์งˆ๋ฌธ ์ค‘ ํ•˜๋‚˜๋Š” ์–ด๋–ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋ชจ๋“  ์‚ฌ๋žŒ์—๊ฒŒ ์™„๋ฒฝํ•œ๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™„๋ฒฝํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—†๋‹ค๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ @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 ํ•˜๋‚˜์˜ ์™„๋ฒฝํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—†์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๊ฝค ์ž˜ ์ž‘๋™ํ•˜๋Š” ์ผ๋ถ€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ฐ„๋‹จํ•˜๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋…ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์œ ์šฉํ•œ ์ž‘์—…์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ณ ๊ธ‰ ์šฉ๋„์˜ ๊ฒฝ์šฐ ๊ทธ ์™ธ์—๋„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชจ์Œ์„ ๊ฐ–๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์ด ์œ ์ผํ•œ ์„ ํƒ์€ ์•„๋‹ˆ์–ด์„œ Dictionary ์— ๋‚ด ๋ฌผ๊ฑด์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก Marvin์ด ๋ˆ„๊ตฐ์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚ด ๋ฌผ๊ฑด์„ ์‚ฌ์ „์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก Marvin์ด ๋ˆ„๊ตฌ์ธ์ง€ ๋ฐฐ์šธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹น์‹ ์ด ๊ทธ๊ฒƒ์„ ๋„ฃ๋Š” ๋ฐฉ์‹์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋˜ํ•œ ๋‹น์‹ ์ด ์‚ฌ์ „ ์ž์ฒด๋ฅผ ์–ธ๊ธ‰ํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. IDictionary๋Š” ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๋‹ค๋ฅธ ํ’ˆ์งˆ์„ ๊ฐ€์ง„ ์ˆ˜๋งŽ์€ ๋‹ค๋ฅธ impls๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋งŽ์€ ํ”Œ๋žซํผ์˜ ์ปฌ๋ ‰์…˜ API ์ฐธ์กฐ). ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ๋ชจ๋“  ๋ฒ”์ฃผ์—์„œ ํƒ์›”ํ•˜์ง€๋Š” ์•Š๋”๋ผ๋„ ์ „๋ฐ˜์ ์œผ๋กœ ๊ดœ์ฐฎ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ธฐ๋ณธ '์‚ฌ์ „'์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ํ†ค์ด ํ•ด์‹ฑ ๋„์„œ๊ด€์—์„œ ๋ฌด์—‡์„ ์ฐพ๊ณ  ๊ทธ์˜๋ฅผ ์ƒ๊ฐํ•œ๋‹ค. ๋ชจ๋“  ๋ชฉ์ ์— ์™„๋ฒฝํ•˜์ง€๋Š” ์•Š๋”๋ผ๋„ ์ž‘์—…์„ ์™„๋ฃŒํ•˜๋Š” ๊ฒƒ.

@morganbr ๋‚ด ์ƒ๊ฐ์— ์‚ฌ๋žŒ๋“ค์€ ํ˜„์žฌ ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๋‚˜์€ GetHashCode๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์›ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(์ผ๋ฐ˜์ ์œผ๋กœ ์›น์—์„œ ๋ณต์‚ฌํ•œ ์ˆ˜ํ•™ ์—ฐ์‚ฐ์˜ ์ผ๋ถ€ ์žก๊ธฐ ์กฐํ•ฉ). ๊ทธ ๋ฃฌ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์•”์‹œ๋งŒ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์‚ฌ๋žŒ๋“ค์€ ํ–‰๋ณตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํŠน์ • ํ•ด์‹ฑ ๊ธฐ๋Šฅ์ด ๋งค์šฐ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๊ณ ๊ธ‰ ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ๋น„ํ•˜์ธ๋“œ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•ด, ์˜ค๋Š˜๋‚  ํ•ด์‹œ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์€ Spooky vs Marvin vs Murmur๋ฅผ ์›ํ•˜๋Š” ์ด์œ ๋ฅผ ์•Œ์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํŠน์ • ํ•ด์‹œ ์ฝ”๋“œ ์ค‘ ํ•˜๋‚˜๊ฐ€ ํŠน๋ณ„ํžˆ ํ•„์š”ํ•œ ์‚ฌ๋žŒ๋งŒ ๊ฒ€์ƒ‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์€ "์—ฌ๊ธฐ ๋‚ด ๊ฐœ์ฒด์˜ ์ƒํƒœ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์ „๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋น ๋ฅด๊ณ  ์ž˜ ๋ถ„์‚ฐ๋œ ํ•ด์‹œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์„ธ์š”. ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ž…๋ ฅ์„ ๋ฐ›์•„ ํ•ด์‹œํ•˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค."

@CyrusNajmabadi ๋ฌธ์ œ๋Š” ํ˜ธํ™˜์„ฑ์— ๋Œ€ํ•œ ํ˜„์žฌ ๊ฐœ๋…์„ ๋ฏธ๋ž˜๋กœ ํ™•์žฅํ•˜๋ฉด ์ด ์œ ํ˜•์ด

Once๋Š” ์•ˆ์ •์ ์ธ ๋ฌด์ž‘์œ„ ๋ฐฉ์‹์œผ๋กœ ์‹œ์ž‘ํ•˜๋ฉด ์‹คํ–‰์—์„œ ์‹คํ–‰์œผ๋กœ ๊ฐ’์— ์˜์กดํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค๊ณ  ์ฃผ์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ช‡ ๋…„ ํ›„ ์šฐ๋ฆฌ๋Š” ํ•ด์‹œ ๋ฒ„ํ‚ท์˜ ๊ท ํ˜•์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•˜์ง€๋งŒ List\

Morgan์˜ ์ œ์•ˆ์— ๋”ฐ๋ฅด๋ฉด ์˜ค๋Š˜ ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ๋Š” ์‚ฌ์‹ค์ƒ ์˜์›ํžˆ ๋™์ผํ•œ ์„ฑ๋Šฅ ํŠน์„ฑ์„ ๊ฐ€์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋” ๋‚˜์•„์งˆ ์ˆ˜ ์žˆ์—ˆ๋˜ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ์€ ๋ถˆํ–‰ํ•œ ์ผ์ž…๋‹ˆ๋‹ค. ๋” ๋‚˜๋น ์กŒ์„ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ์€ ํ™˜์ƒ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒˆ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ฐพ์œผ๋ฉด ์ฒดํฌ์ธํ•˜๊ณ  Roslyn์„ ๋ณ€๊ฒฝํ•˜๊ณ (ReSharper/etc๋กœ ๋ณ€๊ฒฝ ์ œ์•ˆ) SomeThingThatWasConsideredAwesomeIn2018 ๋Œ€์‹  NewAwesomeThing2019๋กœ ์ƒ์„ฑ์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์€ ์Šˆํผ ๋ธ”๋ž™๋ฐ•์Šค๋Š” ๋‹จ ํ•œ ๋ฒˆ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์šฐ๋ฆฌ๋Š” ์˜์›ํžˆ ๋ถ™์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋” ๋‚˜์€ ํ‰๊ท  ์„ฑ๋Šฅ์„ ๊ฐ€์ง„ ๋‹ค์Œ ๊ฒƒ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹น์‹ ์ด ๊ทธ๋“ค ์‚ฌ์ด์—์„œ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋ฅผ ๋ชจ๋ฅด๋Š” ๋‘ ๊ฐœ์˜ ๋ธ”๋ž™๋ฐ•์Šค ๊ตฌํ˜„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ... ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ... .

๋”ฐ๋ผ์„œ Roslyn/ReSharper/etc๊ฐ€ Marvin32, Murmur, FastHash ๋˜๋Š” IntPtr.Size ๊ธฐ๋ฐ˜ ์กฐํ•ฉ/์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜์—ฌ GetHashCode๋ฅผ ์ž๋™์œผ๋กœ ์ž‘์„ฑํ•œ ์ด์œ ๋ฅผ ๋ชจ๋ฅผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹น์‹ ์€ ๊ทธ๊ฒƒ์„ ๋“ค์—ฌ๋‹ค๋ณผ ์ˆ˜ ์žˆ๋Š” ํž˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒˆ๋กœ์šด ์ •๋ณด๊ฐ€ ๊ณต๊ฐœ๋˜๋ฉด ๋‚˜์ค‘์— ์œ ํ˜•์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ๋„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. (๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ์ด๊ฒƒ์„ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ์Šฌํ”ˆ ์ผ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  3๋…„ ์•ˆ์— Roslyn/ReSharper/etc๋Š” ๋ช…์‹œ์ ์œผ๋กœ ๊ทธ๊ฒƒ์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ƒˆ๋กœ์šด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ํ›จ์”ฌ ๋” ๋‚ซ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค... ์ผ๋ฐ˜์ ์œผ๋กœ).

@bartonjs .Net์ด ๋ธ”๋ž™๋ฐ•์Šค ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‚˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ๊ณณ์—์„œ ํ•ด์‹ฑ์ด ๋‹ค๋ฅธ ์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด ์ •๋ ฌ(introsort), Dictionary (๋ฐฐ์—ด ๊ธฐ๋ฐ˜ ๊ฐœ๋ณ„ ์—ฐ๊ฒฐ), StringBuilder (8k ์ฒญํฌ์˜ ์—ฐ๊ฒฐ ๋ชฉ๋ก), ๋Œ€๋ถ€๋ถ„์˜ LINQ.

์˜ค๋Š˜์€ ์ด์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ์•ž๋’ค๋กœ ์ง€์—ฐ๋œ ์  ์‚ฌ๊ณผ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์š”๊ตฌ ์‚ฌํ•ญ

  • ๋ˆ„๊ตฌ๋ฅผ ์œ„ํ•œ API์ž…๋‹ˆ๊นŒ?

    • API ๋Š” ๊ฐ•๋ ฅํ•œ ์•”ํ˜ธํ™” ํ•ด์‹œ๋ฅผ ์ƒ์„ฑ

    • ํ•˜์ง€๋งŒ: API๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ์ž์ฒด(์˜ˆ: BCL ๋ฐ ASP.NET)์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถฉ๋ถ„ํžˆ ์šฐ์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    • ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ๋ชจ๋“  ๊ณณ์—์„œ API๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ๋ณด์•ˆ/DOS ์œ„ํ—˜์„ ์œ„ํ•ด ๋˜๋Š” ์„ฑ๋Šฅ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž ์ง€์ • ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” FX์˜ ์ผ๋ถ€๊ฐ€ ์žˆ์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์˜ˆ์™ธ๋Š” ํ•ญ์ƒ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค .

  • ์ด ํ•ด์‹œ์˜ ์›ํ•˜๋Š” ์†์„ฑ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

    • ์ž…๋ ฅ์˜ ๋ชจ๋“  ๋น„ํŠธ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

    • ๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ๋ถ„๋ฐฐ๋จ

    • API๋Š” "a" ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ํŠน์ • ํ•ด์‹œ ์ฝ”๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋ณด์žฅํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‚˜์ค‘์— ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜์—์„œ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • API๋Š” ์ฃผ์–ด์ง„ ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ ๋™์ผํ•œ ๊ฐ’์ด ๋™์ผํ•œ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๋™์ผํ•œ ์•ฑ์˜ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋Š” ๋ฌด์ž‘์œ„ํ™”๋กœ ์ธํ•ด ๋‹ค๋ฅธ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์†Œ๋น„์ž๊ฐ€ ํ•ด์‹œ ๊ฐ’์„ ์œ ์ง€ํ•˜๊ณ  ์‹ค์ˆ˜๋กœ ์‹คํ–‰(๋˜๋Š” ๋” ๋‚˜์œ ๊ฒฝ์šฐ ํ”Œ๋žซํผ ๋ฒ„์ „)์—์„œ ์•ˆ์ •์ ์ธ ๊ฒƒ์— ์˜์กดํ•˜์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

API ๋ชจ์–‘

```C#
// ์ฝ”์–ด ์–ด์…ˆ๋ธ”๋ฆฌ์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
// .NET ํ”„๋ ˆ์ž„์›Œํฌ: mscorlib
// .NET ์ฝ”์–ด : System.Runtime / System.Private.CoreLib
๋„ค์ž„์ŠคํŽ˜์ด์Šค ์‹œ์Šคํ…œ
{
๊ณต๊ฐœ ๊ตฌ์กฐ์ฒด ํ•ด์‹œ ์ฝ”๋“œ
{
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5, T6 ๊ฐ’6);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5, T6 ๊ฐ’6, T7 ๊ฐ’7);
public static int ๊ฒฐํ•ฉ(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#
๊ณต๊ฐœ ๋ถ€๋ถ„ ํด๋ž˜์Šค ๊ณ ๊ฐ
{
๊ณต๊ฐœ ์žฌ์ •์˜ int GetHashCode() =>
HashCode.Combine(
ID,
StringComparer.OrdinalIgnoreCase.GetHashCode(์ด๋ฆ„),
StringComparer.OrdinalIgnoreCase.GetHashCode(์„ฑ),
);
}

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 ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” StringComparison ๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๊ณณ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋„๋ก comparisonType ๋กœ ์ด๋ฆ„์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๊ธฐ์ค€์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์ข‹์€ ๋ˆˆ์‚ฌํƒœ ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ฆ‰, ์ž…๋ ฅ์˜ ๋ชจ๋“  ๋น„ํŠธ๊ฐ€ ์ถœ๋ ฅ์˜ ๋ชจ๋“  ๋น„ํŠธ๋ฅผ ๋’ค์ง‘์„ ํ™•๋ฅ ์ด 50%์ž…๋‹ˆ๊นŒ? ์ด ์‚ฌ์ดํŠธ ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์ธ๊ธฐ ์žˆ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋Œ€ํ•œ ์—ฐ๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ž‘์€ ์ž…๋ ฅ์— ๋Œ€ํ•ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋น ๋ฆ…๋‹ˆ๊นŒ? HashCode.Combine์€ ์ผ๋ฐ˜์ ์œผ๋กœ 8๊ฐœ ์ดํ•˜์˜ ์ •์ˆ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ์ฒ˜๋ฆฌ๋Ÿ‰๋ณด๋‹ค ๋” ์ค‘์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์‚ฌ์ดํŠธ ์—๋Š” ํฅ๋ฏธ๋กœ์šด ๋ฐ์ดํ„ฐ ์„ธํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋˜ํ•œ ์„œ๋กœ ๋‹ค๋ฅธ ์•„ํ‚คํ…์ฒ˜ ๋˜๋Š” ๊ธฐํƒ€ ํ”ผ๋ฒ—(OS, AoT ๋Œ€ JIT ๋“ฑ)์— ๋Œ€ํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ๋‹ต๋ณ€์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์ •๋ง๋กœ ๋ณด๊ณ  ์‹ถ์€ ๊ฒƒ์€ C#์œผ๋กœ ์ž‘์„ฑ๋œ ํ›„๋ณด์ž์˜ ์„ฑ๋Šฅ ์ˆ˜์น˜์ด๋ฏ€๋กœ ๊ทธ๋“ค์˜ ํŠน์„ฑ์ด .NET์—์„œ ์œ ์ง€๋  ๊ฒƒ์ด๋ผ๊ณ  ํ•ฉ๋ฆฌ์ ์œผ๋กœ ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ํ›„๋ณด๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์ด๊ฒƒ์„ ์œ„ํ•ด ๊ทธ๊ฒƒ์„ ์„ ํƒํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋‚ด๊ฐ€ ์‹ค์ œ๋กœ ๋น„์•”ํ˜ธํ™” ํ•ด์‹œ API์— ๋Œ€ํ•œ API ์ œ์•ˆ์„ ํ•จ๊ป˜ ์–ป์„ ๋•Œ๋งˆ๋‹ค ์—ฌ์ „ํžˆ ์œ ์šฉํ•œ ์ž‘์—…์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ํ‰๊ฐ€ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ›„๋ณด์ž์ž…๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์„ ์ž์œ ๋กญ๊ฒŒ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ์Œ).

  • Marvin32( ์—ฌ๊ธฐ์— ์ด๋ฏธ C# ๊ตฌํ˜„์ด
  • xxHash32 (๊ฐ€์žฅ ๋น ๋ฅธ x86์—์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์—ฌ๊ธฐ SMHasher์— ๋”ฐ๋ผ ์ตœ๊ณ ์˜ ํ’ˆ์งˆ์„ ๊ฐ€์ง€๊ณ )
  • 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 ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” StringComparison ๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋‹ค๋ฅธ ๋ชจ๋“  ๊ณณ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋„๋ก comparisonType ๋กœ ์ด๋ฆ„์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ์ •๋œ.

@CyrusNajmabadi

IMO์—์„œ Add ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ทนํžˆ ๋“œ๋ฌธ ์ผ์ž…๋‹ˆ๋‹ค. ๋งค์šฐ ๊ณ ๊ธ‰ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๋ฉฐ '์œ ์ฐฝํ•œ' ๋Šฅ๋ ฅ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋™์˜.

@benaadams - ์žฌ : ์‹ฌํŒ ๋ฐ˜ํ™˜ this ์—์„œ Add - ์•„๋‹ˆ, this ๊ทธ๊ฒƒ์ด๋ฅผ rvalue ๋˜๋Š” ์ž„์‹œ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌ์กฐ์ฒด ๋ฐฉ๋ฒ•์— ์‹ฌํŒ์— ์˜ํ•ด ๋ฐ˜ํ™˜ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

```C#
์ฐธ์กฐ var r = (์ƒˆ๋กœ์šด 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%(์˜ˆ: 80%๊ฐ€ ์•„๋‹˜)์—์„œ Combine ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋ผ๋ฉด Combine ๊ฐ€ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด์‹ฑ ์ปฌ๋ ‰์…˜์„ ์ง€์›ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ์ปฌ๋ ‰์…˜์—์„œ? ์•„๋งˆ๋„ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ณ„๋„์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค( HashCode ์˜ ํ™•์žฅ ๋ฉ”์„œ๋“œ ๋˜๋Š” ์ •์  ๋ฉ”์„œ๋“œ)?

์ถ”๊ฐ€๊ฐ€ ๊ฐ•๋ ฅํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์ธ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ 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() ๋Š” ๊ฐœ์ฒด์˜ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜์ง€๋งŒ ๋‘ ํ•ด์‹œ ์ฝ”๋“œ๊ฐ€ ๋‹ฌ๋ผ์•ผ ํ•˜๋Š” ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์˜ ๋‘ ์ธ์Šคํ„ด์Šค ์ดํ›„ ์—ฌ์ „ํžˆ ๋งž์Šต๋‹ˆ๋‹ค HashCode ๊ฐ™์€ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€์—์„œ ๊ฐ™์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค 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);

?

@svic

@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"(์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๊ฒฐ์ •ํ–ˆ์ง€๋งŒ). ๊ทธ๋Ÿฌ๋‚˜ ์ตœ์†Œํ•œ ์ด ๋ฐฉ๋ฒ•์€ ์‚ฌ์šฉ์ž๊ฐ€ Intellisense์™€ ๊ฐ™์€ ํ•ญ๋ชฉ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๋ช…ํ™•ํ•œ ๋ฌธ์„œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ „ํ™˜์˜ ๊ฒฝ์šฐ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

typeof(T) == typeof(byte) ์‚ฌ์šฉ์„ ์ „๋ฌธํ™”ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ฐ”์ดํŠธ ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.

IIRC๋Š” ์ด๊ฒƒ์ด JIT ๊ด€์ ์—์„œ ์˜ณ์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์•ฝ๊ฐ„์˜ ์šฐ๋ ค๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ๊ฐ’ ์œ ํ˜•์ด ์•„๋‹Œ "typeof()" ๊ฒฝ์šฐ์—๋งŒ ํ•ด๋‹น๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. jit์ด value-type typeof() ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ํšจ๊ณผ์ ์œผ๋กœ ์˜ฌ๋ฐ”๋ฅธ ์ผ์„ ํ•˜๋Š” ํ•œ ๊ทธ๊ฒƒ์€ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@CyrusNajmabadi int ๋กœ์˜ ๋ณ€ํ™˜์— ์ƒํƒœ ๋ณ€๊ฒฝ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค. ToHashCode ๊ทธ๋Ÿผ.

์•”ํ˜ธํ™” ๊ด€์ ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๋Š” ์‚ฌ๋žŒ๋“ค - http://tuprints.ulb.tu-darmstadt.de/2094/1/thesis.lehmann.pdf

@terrajobst , ๋‚ด ์˜๊ฒฌ( ์—ฌ๊ธฐ ๋ถ€ํ„ฐ ์‹œ์ž‘)์„ ์ฝ๊ณ  ์กฐ์ •๋œ API ๋ชจ์–‘์„ ์Šน์ธํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์‹œ๊ฐ„์ด ์žˆ์—ˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์ด๊ฒƒ์ด api-approved/up for grabs๋กœ ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ๊ณ  ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ฒฐ์ •์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@blowdart , ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์€ ํŠน์ • ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์œ„์—์„œ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋„ˆ๋ฌด ๋ช…์‹œ์ ์ด์ง€ ์•Š์•˜์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ HashDoS ์นจ์ž…์— ๋Œ€ํ•ด ๋‚ด๊ฐ€ ๋ชจ๋ฅด๋Š” ์œ ์ผํ•œ ๋น„์•”ํ˜ธํ™” ํ•ด์‹œ๋Š” Marvin๊ณผ SipHash์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ž„์˜์˜ ๊ฐ’์œผ๋กœ Murmur๋ฅผ ์‹œ๋”ฉ(๋งํ•˜์ž๋ฉด)ํ•˜๋”๋ผ๋„ ์—ฌ์ „ํžˆ ๊นจ์ ธ์„œ DoS์— ์‚ฌ์šฉํ• 

์—†์Œ, ๋ฐฉ๊ธˆ ํฅ๋ฏธ๋กญ๊ฒŒ ๋ณด์•˜๊ณ  ์ด์— ๋Œ€ํ•œ ๋ฌธ์„œ๋Š” "์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ†ตํ•ด ์ƒ์„ฑ๋œ ํ•ด์‹œ ์ฝ”๋“œ์—๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ"์ด๋ผ๊ณ  ๋‚˜์™€ ์žˆ์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ์ •

  • ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ๋ถˆ๋ถ„๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  AddRange ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด์€ ๋งค์šฐ ์ž์ฃผ ๋‚˜ํƒ€๋‚  ๊ฐ€๋Šฅ์„ฑ์ด ๋‹ค์†Œ ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ผ๋‹จ ๋” ํฐ ๋ฐฐ์—ด์ด ๊ด€๋ จ๋˜๋ฉด ๋ฌธ์ œ๋Š” ๊ณ„์‚ฐ์„ ์บ์‹œํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ํ˜ธ์ถœ ์ธก์—์„œ for ๋ฃจํ”„๋ฅผ ๋ณด๋ฉด ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์žˆ์Œ์„ ๋ถ„๋ช…ํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ํ• ๋‹น๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— IEnumerable ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ AddRange ์— ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • string ์™€ StringComparison ๊ฐ€ ๊ฑธ๋ฆฌ๋Š” string Add ๋Œ€ํ•œ ์˜ค๋ฒ„๋กœ๋“œ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ, IEqualityComparer ํ†ตํ•ด ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋‚˜์ค‘์— ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • GetHashCode ๋ฅผ ์˜ค๋ฅ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ์ƒ๊ฐ์ด์ง€๋งŒ ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€ IntelliSense์—์„œ ์ˆจ๊ธธ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ๋‹ค์Œ์„ ๋‚จ๊น๋‹ˆ๋‹ค.

```C#
// ์ฝ”์–ด ์–ด์…ˆ๋ธ”๋ฆฌ์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
// .NET ํ”„๋ ˆ์ž„์›Œํฌ: mscorlib
// .NET ์ฝ”์–ด : System.Runtime / System.Private.CoreLib
๋„ค์ž„์ŠคํŽ˜์ด์Šค ์‹œ์Šคํ…œ
{
๊ณต๊ฐœ ๊ตฌ์กฐ์ฒด ํ•ด์‹œ ์ฝ”๋“œ
{
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5, T6 ๊ฐ’6);
public static int ๊ฒฐํ•ฉ(T1 ๊ฐ’1, T2 ๊ฐ’2, T3 ๊ฐ’3, T4 ๊ฐ’4, T5 ๊ฐ’5, T6 ๊ฐ’6, T7 ๊ฐ’7);
public static int ๊ฒฐํ•ฉ(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++์— ๋Œ€ํ•œ ๋ฐฐ๊ฒฝ ์ง€์‹์ด ๊ฑฐ์˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๊ณ  ํ…Œ์ŠคํŠธ ์•ฑ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์–ด๋ ค์›€์„ ๊ฒช์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ์ตœ์‹  ๋ชฉ๋ก์— ์˜์›ํžˆ ๋‚จ์•„ ์žˆ๊ธฐ๋ฅผ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋ถ€ํ„ฐ ์ผ์ฃผ์ผ ๋™์•ˆ ์•„๋ฌด๋„ ํ•ด๊ฒฐํ•˜์ง€ ์•Š์œผ๋ฉด Programmers SE ๋˜๋Š” 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 ๋ฉ”์„œ๋“œ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ 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๊ฐœ์˜ ํ•˜์œ„ ๋ฐ˜๋ณต์„ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ ๋ฐ˜๋ณต์˜ ์ฒซ ๋ฒˆ์งธ ์ž…๋ ฅ ๊ฐ’์œผ๋กœ ์ด์ „ ํ•˜์œ„ ๋ฐ˜๋ณต์˜ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ํ‰๊ท  ๊ฒฝ๊ณผ ์‹œ๊ฐ„์„ ์–ป๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ๋ฐ˜๋ณต์˜ ํ‰๊ท ์„ ๊ตฌํ•˜๊ณ , ์ด๋ฅผ ๋ฃจํ”„๋‹น ์‹คํ–‰๋˜๋Š” ํ•˜์œ„ ๋ฐ˜๋ณต ์ˆ˜๋กœ ๋” ๋‚˜๋ˆ„์–ด ํ˜ธ์ถœ๋‹น ํ‰๊ท  ์‹œ๊ฐ„์„ ๊ตฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ดˆ๋‹น ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํ˜ธ์ถœ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  ์—ฌ๊ธฐ์— ์‹ค์ œ ์ฒ˜๋ฆฌ๋Ÿ‰์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฒฐํ•ฉ๋œ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์ž ์‹œ ํ›„์— ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

@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

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ๋ฐ์ดํ„ฐ๋Š” ๋™์ผํ•œ ๋‚ด๋ถ€ ํ•ด์‹œ ์ƒํƒœ๋กœ ๊ณต๊ธ‰๋˜์–ด์•ผ ํ•˜๋ฉฐ ํ•ด์‹œ๋Š” ๋งˆ์ง€๋ง‰์— ํ•œ ๋ฒˆ ์ข…๋ฃŒ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘

๊ทธ๊ฒƒ์ด ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์ฐจ์ด์ ์€ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ธ๋ผ์ธํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค( new HashCode() ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ์ƒ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐํ•ฉ๋œ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ์ถ”์ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค).

@morganbr. Murmur3์— ๋Œ€ํ•œ ๊ตฌํ˜„ + ์ฒ˜๋ฆฌ๋Ÿ‰ ํ…Œ์ŠคํŠธ: https://gist.github.com/tannergooding/89bd72f05ab772bfe5ad3a03d6493650

MurmurHash3๋Š” ์—ฌ๊ธฐ์— ์„ค๋ช…๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. https://github.com/aappleby/smhasher/wiki/MurmurHash3 , repo๋Š” MIT๋ผ๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

xxHash32(BSD-2 ์กฐํ•ญ -- https://github.com/Cyan4973/xxHash/blob/dev/xxhash.c) ๋ฐ SpookyHash(๊ณต๊ฐœ ๋„๋ฉ”์ธ -- http://www.burtleburtle.net/bob/hash) ์ž‘์—… /spooky.html) ๋ณ€ํ˜•

@tannergooding ๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ํ•ด์‹œ ์ „๋ฌธ๊ฐ€๋Š” ์•„๋‹ˆ์ง€๋งŒ Murmur๊ฐ€ DoS์— ์ €ํ•ญํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋งํ•œ [๊ธฐ์‚ฌ ์ฝ๊ธฐ][1]๋ฅผ ๊ธฐ์–ตํ•˜๋ฏ€๋กœ ์„ ํƒํ•˜๊ธฐ ์ „์— ์ด๋ฅผ ์ง€์ ํ–ˆ์Šต๋‹ˆ๋‹ค.

@jamesqo , ๋‚ด๊ฐ€ ํ‹€๋ฆด ์ˆ˜๋„ ์žˆ์ง€๋งŒ Murmur3์ด ์•„๋‹Œ Murmur2์— ์ทจ์•ฝ์ ์ด ์ ์šฉ๋˜์—ˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ C#์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋Ÿ‰ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋„๋ก ์—ฌ๋Ÿฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋ถ„ํฌ ๋ฐ ๊ธฐํƒ€ ์†์„ฑ์€ ์ƒ๋‹นํžˆ ์ž˜ ์•Œ๋ ค์ ธ ์žˆ์œผ๋ฏ€๋กœ ๋‚˜์ค‘์— ์–ด๋–ค ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€์ง€ ๊ณ ๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜„

์ด๋Ÿฐ, ๊ธฐ์‚ฌ ๋งํฌ๋ฅผ ์žŠ์—ˆ์Šต๋‹ˆ๋‹ค: http://emboss.github.io/blog/2012/12/14/breaking-murmur-hash-flooding-dos-reloaded/.

@tannergooding ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ณต์ •ํ•œ ์†Œ๋ฆฌ :+1:

@tannergooding , Murmur3 ๊ตฌํ˜„์„ ์‚ดํŽด๋ณด์•˜๋Š”๋ฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์˜ณ๊ณ  ์ตœ์ ํ™”๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ดํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด CombinedValue์™€ Murmur์˜ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€ ๋ชจ๋‘ 32๋น„ํŠธ๋ผ๋Š” ์‚ฌ์‹ค์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์ด๊ฒƒ์€ ์•„๋งˆ๋„ ์ด ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ๊ฝค ์ข‹์€ ์ตœ์ ํ™”์ผ ๊ฒƒ์ด๋ฉฐ ๋‚ด๊ฐ€ ์ด์ „์— ํ˜ผ๋™ํ–ˆ๋˜ ์ผ๋ถ€๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๊ทธ๊ฒƒ์„ ์ฑ„ํƒํ•˜๋ ค๋ฉด ๋ช‡ ๊ฐ€์ง€ ์กฐ์ •์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์•„๋งˆ๋„ ์„ฑ๋Šฅ ์ธก์ •์— ํฐ ์ฐจ์ด๋Š” ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค).

  • ๊ฒฐํ•ฉํ•˜๋‹ค์—ฌ์ „ํžˆ value1์—์„œ CombineValue๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ CombineValue ํ˜ธ์ถœ์€ ์ž„์˜์˜ ์‹œ๋“œ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ToHashCode๋Š” _bytesCombined ๋ฐ _combinedValue๋ฅผ ์žฌ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋™์•ˆ ๋‚ด๊ฐ€ ์ด API๋ฅผ ๊ฐˆ๋งํ•˜๋ฉด์„œ (field1, field2, field3).GetHashCode() ๋ฅผ ํ†ตํ•ด GetHashCode๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ๋‚˜๋นด์Šต๋‹ˆ๊นŒ?

@jnm2 , ValueTuple ํ•ด์‹œ ์ฝ”๋“œ ๊ฒฐํ•ฉ๊ธฐ๋Š” ํ•ด์‹œ ์ฝ”๋“œ์—์„œ ์ž…๋ ฅ์„ ์ˆœ์„œ๋Œ€๋กœ ์ž…๋ ฅํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค(๊ฐ€์žฅ ์ตœ๊ทผ์— ๋‚˜์˜จ ๊ฒƒ์€ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค). ์†Œ์ˆ˜๋กœ ๋‚˜๋ˆ„๋Š” ๋ช‡ ๊ฐœ์˜ ํ•„๋“œ์™€ ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ๊ฒฝ์šฐ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŽ์€ ํ•„๋“œ ๋˜๋Š” 2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ์œผ๋กœ ๋‚˜๋ˆ„๋Š” ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ๊ฒฝ์šฐ ์‚ฝ์ž…ํ•œ ๋งˆ์ง€๋ง‰ ํ•„๋“œ์˜ ์—”ํŠธ๋กœํ”ผ๊ฐ€ ์ถฉ๋Œ ์—ฌ๋ถ€์— ๊ฐ€์žฅ ํฐ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค(์˜ˆ: ๋งˆ์ง€๋ง‰ ํ•„๋“œ๊ฐ€ bool ๋˜๋Š” ์ž‘์€ int์ธ ๊ฒฝ์šฐ guid๋ผ๋ฉด ์•„๋งˆ๋„ ์ถฉ๋Œ์ด ๋งŽ์ด ์ผ์–ด๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ValueTuple์€ ๋ชจ๋‘ 0์ธ ํ•„๋“œ์—์„œ๋„ ์ž˜ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ์ €๋Š” ๋‹ค๋ฅธ ๊ตฌํ˜„ ์ž‘์—…์„ ์ค‘๋‹จํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค(์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋” ๋†’์€ ์ž‘์—…์ด ์žˆ์Œ). ์–ธ์ œ ๋‹ค์‹œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์„์ง€ ๋ฏธ์ง€์ˆ˜์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๊ตฌ์กฐํ™”๋œ ์œ ํ˜•์— ๋Œ€ํ•ด ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํŠœํ”Œ์— ๋Œ€ํ•ด ์ถฉ๋ถ„ํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@jnm2 , ์ด๊ฒƒ์ด ์ด ๊ธฐ๋Šฅ์ด ๊ตฌ์ถ•ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ํ•œ ๊ฐ€์ง€ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ”„๋ ˆ์ž„์›Œํฌ ์ „์ฒด์—์„œ ํ‘œ์ค€ ์ดํ•˜์˜ ํ•ด์‹œ๋ฅผ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ฑ๋Šฅ ๋ฐ ํ’ˆ์งˆ ํŠน์„ฑ์ด ์žˆ๋Š” ๋Œ€๊ทœ๋ชจ ํ•ด์‹œ ํ•จ์ˆ˜ ํ…Œ์ด๋ธ”:
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-32 PoC์— ์ฐฌ์„ฑํ•˜์—ฌ ์‚ฌ๊ฑด์ด ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ข…๊ฒฐ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์–ด๋–ค BTW๊ฐ€ ๋‚˜์—๊ฒŒ ๋งค์šฐ ์ข‹์€ ์„ ํƒ์œผ๋กœ ๋ณด์ด๋ฉฐ ๋” ์ด์ƒ ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์„ ์ง€์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค(ํ•˜์ง€๋งŒ .Add() ํšŒ์›์„ ์‚ญ์ œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค...).

๊ทธ๋Ÿฌ๋‚˜ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋” ๋งŽ์€ ์„ฑ๋Šฅ ์ž‘์—…์„ ๊ณ„์†ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” xx32, xx64, hsip13/24, seahash, murmur3-x86/32์— ๋Œ€ํ•œ ์ผ๋ถ€ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์ ํ™”๋˜์ง€ ์•Š์Œ) sip13/24, spookyv2. City์˜ ์ผ๋ถ€ ๋ฒ„์ „์€ ํ•„์š”ํ•  ๊ฒฝ์šฐ ์ด์‹ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํžˆ ์‰ฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ ๋ฐ˜์ฏค ๋ฒ„๋ ค์ง„ ํ”„๋กœ์ ํŠธ๋Š” ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์—ผ๋‘์— ๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ œ์•ˆ๋œ API์—๋Š” HashCode ํด๋ž˜์Šค๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ฒค์น˜๋งˆํ‚น์„ ์œ„ํ•ด์„œ๋Š” ๊ทธ๋‹ค์ง€ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Definitlyํ•˜์ง€ ์ƒ์‚ฐ ์ค€๋น„ : ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌ ํŒŒ์Šคํƒ€, ๊ณต๊ฒฉ์ ์ธ ์ธ๋ผ์ธ ๋ฐ ์•ˆ์ „์˜ ์•” ์Šคํ”„๋กค๊ณผ ๊ฐ™์€ ๋ฌด์ฐจ๋ณ„์˜ ๊ด€๋Œ€ ํ•œ ๊ธˆ์•ก์„ ์ ์šฉ; ์—”๋””์•ˆ์€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ์ฝ๊ธฐ๋„ ์—†์Šต๋‹ˆ๋‹ค. ref-impl ํ…Œ์ŠคํŠธ ๋ฒกํ„ฐ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ์กฐ์ฐจ๋„ ์™„๊ณกํ•˜๊ฒŒ "๋ถˆ์™„์ „"ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์กฐ๊ธˆ์ด๋ผ๋„ ๋„์›€์ด ๋œ๋‹ค๋ฉด ์•ž์œผ๋กœ 2์ฃผ ๋™์•ˆ ๊ฐ€์žฅ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ฝ”๋“œ์™€ ์ผ๋ถ€ ์˜ˆ๋น„ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ถฉ๋ถ„ํ•œ ์‹œ๊ฐ„์„ ํ™•๋ณดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@๊น€ํ”„

๋‚˜๋Š” ๋ฐฉ๊ธˆ ํ† ๋ก ์„ ์ฝ์—ˆ๊ณ  ์ ์–ด๋„ ๋‚˜์—๊ฒŒ๋Š” murmur3-32 PoC์— ์ฐฌ์„ฑํ•˜์—ฌ ์‚ฌ๊ฑด์ด ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ข…๊ฒฐ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์–ด๋–ค BTW๊ฐ€ ๋‚˜์—๊ฒŒ ๋งค์šฐ ์ข‹์€ ์„ ํƒ์œผ๋กœ ๋ณด์ด๋ฉฐ ๋” ์ด์ƒ ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์„ ์ง€์ถœํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์•„๋‹ˆ์š”, ์‚ฌ๋žŒ๋“ค์€ ์•„์ง Murmur3๋ฅผ ์„ ํ˜ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์„ฑ๋Šฅ/๋ฐฐํฌ ๊ฐ„์˜ ๊ท ํ˜• ์ธก๋ฉด์—์„œ ์ ˆ๋Œ€์ ์œผ๋กœ ์ตœ๊ณ ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋” ๋งŽ์€ ์„ฑ๋Šฅ ์ž‘์—…์„ ๊ณ„์†ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” xx32, xx64, hsip13/24, seahash, murmur3-x86/32์— ๋Œ€ํ•œ ์ผ๋ถ€ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์ ํ™”๋˜์ง€ ์•Š์Œ) sip13/24, spookyv2. City์˜ ์ผ๋ถ€ ๋ฒ„์ „์€ ํ•„์š”ํ•  ๊ฒฝ์šฐ ์ด์‹ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํžˆ ์‰ฌ์›Œ ๋ณด์ž…๋‹ˆ๋‹ค.

์˜ˆ, ๋ถ€ํƒํ•ฉ๋‹ˆ๋‹ค! ์šฐ๋ฆฌ๋Š” ํ…Œ์ŠคํŠธํ•  ๊ฐ€๋Šฅํ•œ ๋งŽ์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ๊ธฐ์—ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ƒˆ๋กœ์šด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. City ์•Œ๊ณ ๋ฆฌ์ฆ˜๋„ ์ด์‹ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ™•์‹คํžˆ ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ๋ณต์‚ฌ ํŒŒ์Šคํƒ€, ๊ณต๊ฒฉ์ ์ธ ์ธ๋ผ์ธ ๋ฐ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์•”์˜ ํ™•์‚ฐ๊ณผ ๊ฐ™์€ ์—„์ฒญ๋‚œ ์–‘์˜ ๋ฌด์ฐจ๋ณ„ ๋Œ€์ž…์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์—”๋””์•ˆ์€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ์ฝ๊ธฐ๋„ ์—†์Šต๋‹ˆ๋‹ค. ref-impl ํ…Œ์ŠคํŠธ ๋ฒกํ„ฐ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ์กฐ์ฐจ๋„ ์™„๊ณกํ•˜๊ฒŒ "๋ถˆ์™„์ „"ํ•ฉ๋‹ˆ๋‹ค.

๊ดœ์ฐฎ์•„. ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ๋งŒ ํ•˜๋ฉด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์กฐ๊ธˆ์ด๋ผ๋„ ๋„์›€์ด ๋œ๋‹ค๋ฉด ์•ž์œผ๋กœ 2์ฃผ ๋™์•ˆ ๊ฐ€์žฅ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ฝ”๋“œ์™€ ์ผ๋ถ€ ์˜ˆ๋น„ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ถฉ๋ถ„ํ•œ ์‹œ๊ฐ„์„ ํ™•๋ณดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜ ๊ทธ๊ฒŒ ์ข‹๊ฒ ๋‹ค!

@jamesqo ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค . ๋ณด์—ฌ๋“œ๋ฆด ๊ฒƒ์ด ์žˆ์œผ๋ฉด ๋ฉ”๋ชจํ•ด

@gimpf ์ •๋ง ํ›Œ๋ฅญํ•˜๊ฒŒ ๋“ค๋ฆฌ๊ณ  ์ง„ํ–‰ ์ƒํ™ฉ์— ๋Œ€ํ•ด ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค(๋ชจ๋“  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์™„๋ฃŒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค!). ์ฝ”๋“œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„ฑ๋Šฅ์ด ํ”„๋กœ๋•์…˜ ์ค€๋น„ ๊ตฌํ˜„์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ์ž˜ ํ‘œํ˜„ํ•œ๋‹ค๊ณ  ๋ฏฟ๋Š” ํ•œ ํ”„๋กœ๋•์…˜ ์ค€๋น„๊ฐ€ ๋˜์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ํ›„๋ณด์ž๋ฅผ ์„ ํƒํ•˜๋ฉด ๊ณ ํ’ˆ์งˆ ๊ตฌํ˜„์„ ์œ„ํ•ด ๊ท€ํ•˜์™€ ํ˜‘๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

seahash์˜ ์—”ํŠธ๋กœํ”ผ๊ฐ€ ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์–ด๋–ป๊ฒŒ ๋น„๊ต๋˜๋Š”์ง€์— ๋Œ€ํ•œ ๋ถ„์„์„ ๋ณธ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ํฅ๋ฏธ๋กœ์šด ์„ฑ๋Šฅ ์ ˆ์ถฉ์•ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค... ๋ฒกํ„ฐํ™”๋Š” ๋น ๋ฅด๊ฒŒ ๋“ค๋ฆฌ์ง€๋งŒ ๋ชจ๋“ˆ์‹ ์‚ฐ์ˆ ์€ ๋Š๋ฆฌ๊ฒŒ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

@morganbr ํ‹ฐ์ € ์ค€๋น„ํ–ˆ์Šต๋‹ˆ๋‹ค.

SeaHash ์†Œ๊ฐœ : ์•„๋‹ˆ์š”, ํ’ˆ์งˆ์— ๋Œ€ํ•ด์„œ๋Š” ์•„์ง ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ์„ฑ๋Šฅ์ด ํฅ๋ฏธ๋กœ์šด ๊ฒฝ์šฐ SMHasher์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ ์–ด๋„ ์ €์ž๋Š” ๊ทธ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์ฃผ์žฅํ•˜๊ณ (ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ์ฒดํฌ์„ฌ์— ์‚ฌ์šฉ), ๋˜ํ•œ ๋ฏน์‹ฑ ์ค‘์— ์—”ํŠธ๋กœํ”ผ๊ฐ€ ๋ฒ„๋ ค์ง€์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค.

ํ•ด์‹œ ๋ฐ ๋ฒค์น˜๋งˆํฌ ์ •๋ณด : ํ”„๋กœ์ ํŠธ Haschisch.Kastriert , xx32, xx64, hsip13, hsip24, marvin32, sea ๋ฐ murmur3-32๋ฅผ ๋น„๊ต ํ•œ ์ฒซ ๋ฒˆ์งธ ๋ฒค์น˜๋งˆํ‚น ๊ฒฐ๊ณผ๊ฐ€ ์žˆ๋Š” ์œ„ํ‚ค ํŽ˜์ด์ง€.

๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ฃผ์˜ ์‚ฌํ•ญ:

  • ์ด๊ฒƒ์€ ๋‚ฎ์€ ์ •ํ™•๋„ ์„ค์ •์œผ๋กœ ๋งค์šฐ ๋น ๋ฅธ ๋ฒค์น˜ ๋Ÿฐ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ตฌํ˜„์ด ์•„์ง ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์œผ๋ฉฐ ์ผ๋ถ€ ๊ฒฝ์Ÿ์ž๊ฐ€ ์—ฌ์ „ํžˆ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ŠคํŠธ๋ฆฌ๋ฐ ๊ตฌํ˜„(์ด์™€ ๊ฐ™์€ ๊ฒƒ์€ ํ•ฉ๋ฆฌ์ ์ธ .Add() ์ง€์›์— ํ•„์š”ํ•จ)์€ ์‹ค์ œ ์ตœ์ ํ™”๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • SeaHash๋Š” ํ˜„์žฌ ์‹œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฒซ์ธ์ƒ:

  • ๋Œ€์šฉ๋Ÿ‰ ๋ฉ”์‹œ์ง€์˜ ๊ฒฝ์šฐ xx64๊ฐ€ ๋‚˜์—ด๋œ ๊ตฌํ˜„ ์ค‘ ๊ฐ€์žฅ ๋น ๋ฆ…๋‹ˆ๋‹ค(๋‚ด๊ฐ€ ์ดํ•ดํ•˜๋Š” ํ•œ ์ฃผ๊ธฐ๋‹น ์•ฝ 3.25๋ฐ”์ดํŠธ ๋˜๋Š” ๋…ธํŠธ๋ถ์˜ ๊ฒฝ์šฐ 9.5GiB/s)
  • ์งง์€ ๋ฉ”์‹œ์ง€์˜ ๊ฒฝ์šฐ ์•„๋ฌด ๊ฒƒ๋„ ํ›Œ๋ฅญํ•˜์ง€ ์•Š์ง€๋งŒ murmur3-32 ๋ฐ (๋†€๋ž๊ฒŒ๋„) seahash๊ฐ€ ์œ ๋ฆฌํ•˜์ง€๋งŒ ํ›„์ž๋Š” ์•„์ง ์”จ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” seahash๋กœ ์„ค๋ช…๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.
  • HashSet<> ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•œ "๋ฒค์น˜๋งˆํฌ"๋Š” ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ๊ฑฐ์˜ ์ธก์ • ์˜ค๋ฅ˜ ๋‚ด์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๋” ํฐ ์ฐจ์ด๋ฅผ ๋ณด์•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์ด์•ผ๊ธฐํ•  ๊ฐ€์น˜๊ฐ€ ์—†์Œ)
  • ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฒฐํ•ฉํ•  ๋•Œ murmur-3A PoC๋Š” ์—ฌ๊ธฐ์— ์žˆ๋Š” ๊ฒƒ๋ณด๋‹ค ์•ฝ 5~20๋ฐฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.
  • C#์˜ ์ผ๋ถ€ ์ถ”์ƒํ™”๋Š” ๋งค์šฐ ๋น„์Œ‰๋‹ˆ๋‹ค. ์ด๋Š” ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์„ ํ•„์š” ์ด์ƒ์œผ๋กœ ์„ฑ๊ฐ€์‹œ๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ƒํ™ฉ์ด ์กฐ๊ธˆ ๋‚˜์•„์ง€๋ฉด ๋‹ค์‹œ ๊ธ€์„ ์“ฐ๊ฒ ์Šต๋‹ˆ๋‹ค.

@gimpf , ํ™˜์ƒ์ ์ธ ์‹œ์ž‘์ž…๋‹ˆ๋‹ค! ์ฝ”๋“œ์™€ ๊ฒฐ๊ณผ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ๋ช‡ ๊ฐ€์ง€ ์งˆ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ฒฐ๊ณผ๋Š” SimpleMultiplyAdd๊ฐ€ @tannergooding ์˜ Murmur3a๋ณด๋‹ค ์•ฝ 5๋ฐฐ ๋Š๋ฆฐ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Murmur๊ฐ€ ๊ณฑํ•˜๊ธฐ+๋”ํ•˜๊ธฐ๋ณด๋‹ค ํ•ด์•ผ ํ•  ์ผ์ด ๋” ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ƒํ•ด ๋ณด์ž…๋‹ˆ๋‹ค(๋ฌผ๋ก  ํšŒ์ „์ด ๋”ํ•˜๊ธฐ๋ณด๋‹ค ๋” ๋น ๋ฅธ ์ž‘์—…์ด๋ผ๋Š” ์ ์€ ์ธ์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค). ๊ท€ํ•˜์˜ ๊ตฌํ˜„์— Murmur ๊ตฌํ˜„์— ์—†๋Š” ์ผ๋ฐ˜์ ์ธ ๋น„ํšจ์œจ์„ฑ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ด๊ฒƒ์„ ๋ฒ”์šฉ ๊ตฌํ˜„๋ณด๋‹ค ํฐ ์ด์ ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌํ˜„์œผ๋กœ ์ฝ์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?
  2. 1, 2, 4 ์กฐํ•ฉ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์œผ๋ฉด ์ข‹์ง€๋งŒ ์ด API๋Š” ์ตœ๋Œ€ 8๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ๋„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ค‘๋ณต์ด ๋„ˆ๋ฌด ๋งŽ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ?
  3. ๋‚˜๋Š” ๋‹น์‹ ์ด X64์—์„œ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์•˜์œผ๋ฏ€๋กœ ์ด ๊ฒฐ๊ณผ๋Š” ์šฐ๋ฆฌ์˜ X64 ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ด์ง€๋งŒ ๋‹ค๋ฅธ ๋ฒค์น˜๋งˆํฌ์—์„œ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด X86๊ณผ X64 ์‚ฌ์ด์—์„œ ์ƒ๋‹นํžˆ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ์„ ์‹œ์‚ฌํ•ฉ๋‹ˆ๋‹ค. X86 ๊ฒฐ๊ณผ๋„ ์‰ฝ๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? (์–ธ์  ๊ฐ€๋Š” ARM๊ณผ ARM64๋„ ํ•„์š”ํ•˜๊ฒ ์ง€๋งŒ, ํ™•์‹คํžˆ ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)

HashSet ๊ฒฐ๊ณผ๋Š” ํŠนํžˆ ํฅ๋ฏธ๋กญ์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์ด ์œ ์ง€ํ•œ๋‹ค๋ฉด ๋” ๋น ๋ฅธ ํ•ด์‹œ ์‹œ๊ฐ„๋ณด๋‹ค ๋” ๋‚˜์€ ์—”ํŠธ๋กœํ”ผ๋ฅผ ์„ ํ˜ธํ•˜๋Š” ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

@morganbr ์ด๋ฒˆ ์ฃผ๋ง์€ ๋” ๋งŽ์ด

๊ท€ํ•˜์˜ ์งˆ๋ฌธ์— ๋Œ€ํ•ด:

  1. ๊ฒฐ๊ณผ๋Š” SimpleMultiplyAdd๊ฐ€ @tannergooding ์˜ Murmur3a๋ณด๋‹ค ์•ฝ 5๋ฐฐ ๋Š๋ฆฐ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด์ƒํ•ด ๋ณด์ด๋Š”๋ฐ...

๋‚˜๋Š” ๋‚˜ ์ž์‹ ์ด ๊ถ๊ธˆํ–ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐ ์˜ค๋ฅ˜์˜€์Šต๋‹ˆ๋‹ค. SimpleMultiplyAdd๋Š” ํ•ญ์ƒ 4๊ฐœ์˜ ๊ฐ’์„ ๊ฒฐํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค... ๋˜ํ•œ ์ผ๋ถ€ ๋ช…๋ น๋ฌธ์„ ์žฌ์ •๋ ฌํ•จ์œผ๋กœ์จ ๊ณฑํ•˜๊ธฐ-๋”ํ•˜๊ธฐ ๊ฒฐํ•ฉ๊ธฐ๊ฐ€ ์•ฝ๊ฐ„ ๋” ๋นจ๋ผ์กŒ์Šต๋‹ˆ๋‹ค(~60% ๋” ๋†’์€ ์ฒ˜๋ฆฌ๋Ÿ‰).

๊ท€ํ•˜์˜ ๊ตฌํ˜„์— Murmur ๊ตฌํ˜„์— ์—†๋Š” ์ผ๋ฐ˜์ ์ธ ๋น„ํšจ์œจ์„ฑ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ด๊ฒƒ์„ ๋ฒ”์šฉ ๊ตฌํ˜„๋ณด๋‹ค ํฐ ์ด์ ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌํ˜„์œผ๋กœ ์ฝ์–ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๋ช‡ ๊ฐ€์ง€๋ฅผ ๋†“์น  ์ˆ˜ ์žˆ์ง€๋งŒ .NET์˜ ๊ฒฝ์šฐ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€์—๋Š” ๋ฒ”์šฉ ๊ตฌํ˜„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ชจ๋“  ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋Œ€ํ•ด Combine ์Šคํƒ€์ผ ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์œผ๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ wrt ํ•ด์‹œ ์ฝ”๋“œ ๊ฒฐํ•ฉ์ด ๋ฒ”์šฉ ๋ฉ”์†Œ๋“œ๋ณด๋‹ค _ํ›จ์”ฌ_ ๋” ์ž˜ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ๊ตฌํ˜„์กฐ์ฐจ๋„ ์—ฌ์ „ํžˆ ๋„ˆ๋ฌด ๋Š๋ฆฝ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜์—ญ์˜ .NET ์„ฑ๋Šฅ์€ ๋‚˜์—๊ฒŒ ์ ˆ๋Œ€์ ์œผ๋กœ ๋ถˆํˆฌ๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ๋ณ€์ˆ˜์˜ ๋ณต์‚ฌ๋ณธ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋ฉด ์„ฑ๋Šฅ์ด 2๋ฐฐ ์ •๋„ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ตœ์ƒ์˜ ์˜ต์…˜์„ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•ด ์ถฉ๋ถ„ํžˆ ์ž˜ ์ตœ์ ํ™”๋œ ๊ตฌํ˜„์„ ์ œ๊ณตํ•  ์ˆ˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  1. 1, 2, 4 ์กฐํ•ฉ์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์œผ๋ฉด ์ข‹์ง€๋งŒ ์ด API๋Š” 8๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค.

๊ฒฐํ•ฉ ๋ฒค์น˜๋งˆํฌ๋ฅผ ํ™•์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ „๋ฉด์— ๋†€๋ผ์›€์ด ์—†์Šต๋‹ˆ๋‹ค.

  1. X64(...)์—์„œ ์‹คํ–‰ํ•œ ๊ฒƒ์„ ๋ณด์•˜๋Š”๋ฐ, X86 ๊ฒฐ๊ณผ๋„ ์‰ฝ๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ๋‚˜์š”?

์˜ˆ์ „์—๋Š” ๊ทธ๋žฌ์ง€๋งŒ .NET Standard๋กœ ์ด์‹ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์ €๋Š” ์ข…์†์„ฑ ์ง€์˜ฅ์— ์žˆ์œผ๋ฉฐ .NET Core 2 ๋ฐ CLR 64๋น„ํŠธ ๋ฒค์น˜๋งˆํฌ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ˜„์žฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด ์ถฉ๋ถ„ํžˆ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด v2.1 ๋ฆด๋ฆฌ์Šค์—์„œ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ?

@gimpf ํ•œ๋™์•ˆ ๊ฒŒ์‹œ๋ฌผ์„ ์˜ฌ๋ฆฌ์ง€ ์•Š์œผ์…จ์Šต๋‹ˆ๋‹ค. ๊ตฌํ˜„์— ๋Œ€ํ•œ ์ง„ํ–‰ ์ƒํ™ฉ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? : ์Šค๋งˆ์ผ :

@jamesqo ์ด์ƒํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•˜๋Š” ๋ฒค์น˜๋งˆํฌ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ชฉ๋ก์— City32, SpookyV2, Sip13 ๋ฐ Sip24๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. Sip์€ ์˜ˆ์ƒ๋Œ€๋กœ ๋น ๋ฅด๋ฉฐ(xx64์˜ ์ฒ˜๋ฆฌ๋Ÿ‰์— ๋น„ํ•ด) City์™€ Spooky๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค(SeaHash์˜ ๊ฒฝ์šฐ์—๋„ ๋™์ผ).

ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฒฐํ•ฉํ•˜๋Š” ๊ฒฝ์šฐ Murmur3-32๊ฐ€ ์—ฌ์ „ํžˆ ์ข‹์€ ์„ ํƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์•„์ง ๋” ์ฒ ์ €ํ•œ ๋น„๊ต๋ฅผ ์‹คํ–‰ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ์ฐธ๊ณ  ์‚ฌํ•ญ์œผ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐ API(.Add())๋Š” ํ›„๋ณด ๋ชฉ๋ก์—์„œ ์ผ๋ถ€ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ œ๊ฑฐํ•˜๋Š” ๋ถˆํ–‰ํ•œ ๋ถ€์ž‘์šฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌํ•œ API์˜ ์„ฑ๋Šฅ๋„ ์˜์‹ฌ์Šค๋Ÿฝ๋‹ค๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ œ๊ณตํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

.Add() ๋ถ€๋ถ„์„ โ€‹โ€‹ํ”ผํ•˜๊ณ  ํ•ด์‹œ ๊ฒฐํ•ฉ๊ธฐ๊ฐ€ ์‹œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ tg์˜ ๊ฒฐํ•ฉ๊ธฐ๋ฅผ ์ •๋ฆฌํ•˜๊ณ  ์ž‘์€ ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„ ๊ทธ๋งŒํ•˜๊ธฐ๋กœํ•˜๋‹ค. ์ฃผ๋ง๋งˆ๋‹ค ๋ช‡ ์‹œ๊ฐ„ ๋ฐ–์— ์•ˆ ํ•˜๊ณ  ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ๋‹ค์†Œ ์ง€๋ฃจํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธˆ๋„๊ธˆ ๋ฒ„์ „์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์•ฝ๊ฐ„ ์ง€๋ฃจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ...

@gimpf , ๋Œ€๋‹จํ•œ ์ง„์ „์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ณ  ์•ž์œผ๋กœ ๋‚˜์•„๊ฐˆ ๋งŒํผ ์ถฉ๋ถ„ํ•œ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฒฐ๊ณผ ํ…Œ์ด๋ธ”์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@morganbr ๋ฒค์น˜๋งˆํ‚น ๊ฒฐ๊ณผ๋ฅผ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ์€ .NET Core 2์—์„œ 64๋น„ํŠธ ๊ฒฐ๊ณผ๋งŒ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ํ”Œ๋žซํผ์˜ ๊ฒฝ์šฐ City64 w/o seed๊ฐ€ ๋ชจ๋“  ํฌ๊ธฐ์—์„œ ๊ฐ€์žฅ ๋น ๋ฆ…๋‹ˆ๋‹ค. ์ข…์ž๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ XX-32๋Š” Murmur-3-32์™€ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์šด ์ข‹๊ฒŒ๋„ ์ด๊ฒƒ๋“ค์€ 32๋น„ํŠธ ํ”Œ๋žซํผ์—์„œ ๋น ๋ฅธ ๊ฒƒ์œผ๋กœ ํ‰ํŒ์ด ์ข‹์€ ๋™์ผํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด์ง€๋งŒ ๋ถ„๋ช…ํžˆ ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์ด ์ œ ๊ตฌํ˜„์—๋„ ์ ์šฉ๋˜๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Sea์™€ SpookyV2๊ฐ€ ๋น„์ •์ƒ์ ์œผ๋กœ ๋Š๋ฆฐ ๊ฒƒ์„ ์ œ์™ธํ•˜๊ณ  ๊ฒฐ๊ณผ๋Š” ์‹ค์ œ ์„ฑ๋Šฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ•ด์‹œ ์ฝ”๋“œ ๊ฒฐํ•ฉ๊ธฐ์— ๋Œ€ํ•œ ํ•ด์‹œ ๋„์Šค ๋ณดํ˜ธ๊ฐ€ ์–ผ๋งˆ๋‚˜ ํ•„์š”ํ•œ์ง€ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹œ๋“œ๊ฐ€ ํ•ด์‹œ๋ฅผ ์ง€์†์„ฑ์„ ์œ„ํ•ด ๋ถ„๋ช…ํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋„๋ก ๋งŒ๋“œ๋Š” ๋ฐ๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ 32๋น„ํŠธ ์‹œ๋“œ๋กœ XORํ•˜๋ฉด city64๊ฐ€ ๊ฐœ์„ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ํ•ด์‹œ๋ฅผ ๊ฒฐํ•ฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋งŒ ์กด์žฌํ•˜๋ฏ€๋กœ(์˜ˆ๋ฅผ ๋“ค์–ด ๋ฌธ์ž์—ด์˜ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋Œ€์ฒดํ•˜๊ฑฐ๋‚˜ ์ •์ˆ˜ ๋ฐฐ์—ด ๋“ฑ์˜ ๋“œ๋กญ์ธ ํ•ด์‹œ๊ฐ€ ๋˜์ง€ ์•Š์Œ) ์ถฉ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

OTOH๊ฐ€ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค๋ฉด Sip13์ด ์ผ๋ฐ˜์ ์œผ๋กœ XX-32(64๋น„ํŠธ ํ”Œ๋žซํผ์—์„œ)๋ณด๋‹ค 50% ๋ฏธ๋งŒ ๋Š๋ฆฌ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ ๊ฒฐ๊ณผ๋Š” 32๋น„ํŠธ ์•ฑ์—์„œ ํฌ๊ฒŒ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

corefx์™€ ์–ผ๋งˆ๋‚˜ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ๋ชจ๋ฅด์ง€๋งŒ LegacyJit 32๋น„ํŠธ(w/FW 4.7) ๊ฒฐ๊ณผ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ๊ฐ€ ํ„ฐ๋ฌด๋‹ˆ์—†์ด ๋Š๋ฆฌ๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์˜ˆ๋ฅผ ๋“ค์–ด, 56 MiB/s ๋Œ€ 319 MiB/s์—์„œ ๋‚˜๋Š” ์›ƒ์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ฆ‰, Sip, ์™ผ์ชฝ ํšŒ์ „ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€์žฅ ๋ˆ„๋ฝ๋จ). 1์›”์— .NET ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ทจ์†Œํ•œ ์ด์œ ๋ฅผ ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค...

๋”ฐ๋ผ์„œ RyuJit-32bit๋Š” ์—ฌ์ „ํžˆ ๋ˆ„๋ฝ๋˜์—ˆ์œผ๋ฉฐ (๋ฐ”๋ผ๊ฑด๋Œ€) ๋งค์šฐ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•  ๊ฒƒ์ด์ง€๋งŒ LegacyJit-x86์˜ ๊ฒฝ์šฐ Murmur-3-32๊ฐ€ ์‰ฝ๊ฒŒ ์Šน๋ฆฌํ•˜๊ณ  City-32์™€ xx-32๋งŒ ๊ทผ์ ‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Murmur๋Š” ์—ฌ์ „ํžˆ 0.6~2GB/s๊ฐ€ ์•„๋‹Œ ์•ฝ 0.4~1.1GB/s๋กœ ์„ฑ๋Šฅ์ด ์ข‹์ง€ ์•Š์ง€๋งŒ(๋™์ผํ•œ ์‹œ์Šคํ…œ์—์„œ), ์ ์–ด๋„ ์ ์ ˆํ•œ ์ˆ˜์ค€์— ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ค๋Š˜ ๋ฐค ๋ช‡ ๋Œ€์˜ ์ œํ’ˆ์— ๋Œ€ํ•ด ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๊ฒŒ์‹œํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค(Ryzen, i7, Xeon, A10, i7 Mobile ๋ฐ ๊ธฐํƒ€ ๋ช‡ ๊ฐ€์ง€).

@tannergooding @morganbr ๋ช‡ ๊ฐ€์ง€ ํ›Œ๋ฅญํ•˜๊ณ  ์ค‘์š”ํ•œ ์—…๋ฐ์ดํŠธ์ž…๋‹ˆ๋‹ค.

์ค‘์š”ํ•œ ์ฒซ ๋ฒˆ์งธ:

  • ์ž˜๋ชป๋œ ํ•ด์‹œ ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” ์ผ๋ถ€ ๊ฒฐํ•ฉ ๊ตฌํ˜„์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด์ œ ๋ฒค์น˜๋งˆํฌ ์ œํ’ˆ๊ตฐ์€ ์ง€์†์ ์ธ ์ ‘๊ธฐ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ๋” ์—ด์‹ฌํžˆ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. City64๋Š” ์ทจ์•ฝํ–ˆ์Šต๋‹ˆ๋‹ค(๊ณผ๊ฑฐ์˜ murmur-3-32์ฒ˜๋Ÿผ). ๋‚ด๊ฐ€ ์ง€๊ธˆ ๋ชจ๋“  ๊ฒฐ๊ณผ๋ฅผ ์ดํ•ดํ•œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹ˆ์ง€๋งŒ ํ›จ์”ฌ ๋” ๊ทธ๋Ÿด๋“ฏํ•ฉ๋‹ˆ๋‹ค.

์ข‹์€ ๊ฒƒ๋“ค:

  • ๊ฒฐํ•ฉ๊ธฐ ๊ตฌํ˜„์€ ์ด์ œ xx/city์— ๋Œ€ํ•œ ๋‹ค์†Œ ๋ฒˆ๊ฑฐ๋กœ์šด ์ˆ˜๋™ ์–ธ๋กค ๊ตฌํ˜„์„ ํฌํ•จํ•˜์—ฌ ๋ชจ๋“  1-8 ์ธ์ˆ˜ ์˜ค๋ฒ„๋กœ๋“œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ์™€ ๋ฒค์น˜๋งˆํฌ๋„ ์ด๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—๋Š” ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์˜ ๋กœ์šฐ ๋ฐ”์ดํŠธ ๋ฉ”์‹œ์ง€๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์ธก์ •์ด ์ค‘์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—ฌ๋Ÿฌ ๋Œ€์ƒ์— ๋Œ€ํ•œ ์‹คํ–‰ ๋ฒค์น˜๋งˆํฌ๋ฅผ ๊ฐ„์†Œํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค(Core vs. 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์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ : ๋ชจ๋“  ๋ฒ„๊ทธ ์ˆ˜์ • ํ›„ "๋น ๋ฅธ" ์‹คํ–‰์—์„œ ๋ชจ๋ฐ”์ผ Haswell i7์˜ Windows 10์—์„œ xx32๊ฐ€ 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. ๋จธ๋จธ3A

HashDoS ๋‚ด์„ฑ:

  • ๋งˆ๋นˆ32
  • ์‹ญํ•ด์‹œ. ์ด ์ชฝ์œผ๋กœ ๊ธฐ์šธ๋ฉด ์—ฐ๊ตฌ ๊ฒฐ๊ณผ๊ฐ€ ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด Microsoft์˜ ์•”ํ˜ธํ™” ์ „๋ฌธ๊ฐ€์—๊ฒŒ ๊ฒ€ํ† ๋ฅผ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ์–ด๋–ค ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ถฉ๋ถ„ํžˆ ์•ˆ์ „ํ•œ์ง€ ์•Œ์•„๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋…ผ๋ฌธ ์€ Sip-2-4์™€ Sip-4-8 ์‚ฌ์ด์˜ ์–ด๋”˜๊ฐ€๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

๊ฒฝํ•ฉ ์—†์Œ(๋Š๋ฆผ):

  • ์œผ์Šค์Šคํ•œ V2
  • ์‹œํ‹ฐ32
  • xxHash64
    *SeaHash(์—”ํŠธ๋กœํ”ผ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์Œ)

๊ฒฝํ•ฉ ์—†์Œ(๋‚˜์œ ์—”ํŠธ๋กœํ”ผ):

  • ๊ณฑํ•˜๊ธฐ ๋”ํ•˜๊ธฐ
  • HSip

์šฐ์Šน์ž๋ฅผ ์„ ํƒํ•˜๊ธฐ ์ „์— ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์œ„์˜ ๋ฒ„ํ‚ท์— ๋™์˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์œ ์ง€๋œ๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” HashDoS ์ €ํ•ญ์— ๋Œ€ํ•ด 2๋ฐฐ๋ฅผ ์ง€๋ถˆํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ ํƒํ•œ ๋‹ค์Œ ์†๋„์— ๋”ฐ๋ผ ๊ฐ€์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@morganbr ๊ทธ๋ฃนํ™”๊ฐ€ ์ž˜ ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. SipHash ๋ผ์šด๋“œ์˜ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ๋กœ์„œ Rust ํ”„๋กœ์ ํŠธ๋Š” sip-hash w/DJB๋ฅผ ์ž‘์„ฑํ•œ Jean-Philippe Aumasson ์—๊ฒŒ ์งˆ๋ฌธํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋…ผ์˜ ํ›„์— ๊ทธ๋“ค์€ ํ•ด์‹œ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•ด 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#
๊ณต๊ฐœ ํ•ด์‹œ์ฝ”๋“œ ์ถ”๊ฐ€(T ๊ฐ’);
๊ณต๊ฐœ ํ•ด์‹œ์ฝ”๋“œ ์ถ”๊ฐ€(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();

๊ทธ๋Ÿฌ๋‚˜ ํ•˜๋‚˜์˜ ๋œ ๋‚ญ๋น„์ ์ธ ๋ฐฐ์—ด ํ• ๋‹น์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •ํ™•ํžˆ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์œ ํ˜•์„ ํ˜ผํ•ฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ถ„๋ช…ํžˆ ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ๋‚ด์—์„œ ์œ ์ฐฝํ•˜๊ฒŒ ํ˜ธ์ถœ ํ•˜์ง€ ์•Š์Œ ์œผ๋กœ์จ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ์ฐฝํ•œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ ˆ๋Œ€์ ์œผ๋กœ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋Š” ์ด ์ฃผ์žฅ์„ ๊ฐ์•ˆํ•  ๋•Œ ์ฒ˜์Œ์—๋Š” ๋‚ญ๋น„์ ์ธ params ์˜ค๋ฒ„๋กœ๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ด ์ œ์•ˆ์ด ์ž˜๋ชป๋œ ์ œ์•ˆ์ด๋ผ๋ฉด params ์˜ค๋ฒ„๋กœ๋“œ๋Š” ๋™์ผํ•œ ์ถ•์œผ๋กœ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์†Œํ•˜์ง€๋งŒ ์ตœ์ ์˜ ํ•ด์‹œ์ฝ”๋“œ์— ๋Œ€ํ•œ ์ •๊ทœ์ ์ธ ๋ฐฉ๋ฒ•์„ ๊ฐ•์š”ํ•˜๋Š” ๊ฒƒ์€ ๋งŽ์€ ์˜์‹์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

ํŽธ์ง‘: implicit operator int ๋Š” DRY์—๋„ ์ข‹์ง€๋งŒ ์ •ํ™•ํžˆ ์ค‘์š”ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

@jcdickinson

Add ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๊นŒ?

์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์ด์ „ ์ œ์•ˆ์—์„œ ๋…ผ์˜ํ–ˆ์ง€๋งŒ ๊ฑฐ๋ถ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚ญ๋น„์ ์ธ params ๊ณผ๋ถ€ํ•˜๊ฐ€ ์ฒ˜์Œ์— ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

params ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์ด ์›น ํŽ˜์ด์ง€์—์„œ "params"์— ๋Œ€ํ•ด Ctrl+F๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ํ•ด๋‹น ๋‹จ์–ด๊ฐ€ ํ‘œ์‹œ๋˜๋Š” ์œ ์ผํ•œ ์œ„์น˜์— ๊ท€ํ•˜์˜ ๋Œ“๊ธ€์ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•”์‹œ์  ์—ฐ์‚ฐ์ž int๋„ DRY์— ์ ํ•ฉํ•˜์ง€๋งŒ ์ •ํ™•ํžˆ ์ค‘์š”ํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

์œ„์˜ ์–ด๋”˜๊ฐ€์—์„œ ๋…ผ์˜ ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ...

@jamesqo ์„ค๋ช… ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜ ์˜ค๋ฒ„๋กœ๋“œ

๋‚˜๋Š” 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ํšŒ ํ˜ธ์ถœ๊ณผ ์œ ์ฐฝํ•œ ํ™•์žฅ ๋ฐฉ๋ฒ•:

| ๋ฐฉ๋ฒ• | ํ‰๊ท  | ์˜ค๋ฅ˜ | ํ‘œ์ค€ ๊ฐœ๋ฐœ | ์Šค์ผ€์ผ |
|--------- |---------:|---------:|---------:|---------: |
| ์ถ”๊ฐ€ | 401.6ns | 1.262ns | 1.180ns | 1.00 |
| ํƒˆ๋ฆฌ | 747.8ns | 2.329ns | 2.178ns | 1.86 |

๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ ํŒจํ„ด์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

```c#
๊ณต๊ฐœ ๊ตฌ์กฐ์ฒด HashCode : System.Collections.IEnumerable
{
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("์ด ๋ฉ”์„œ๋“œ๋Š” ์ปฌ๋ ‰์…˜ ์ด๋‹ˆ์…œ๋ผ์ด์ € ๊ตฌ๋ฌธ์— ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.", ์˜ค๋ฅ˜: true)]
public IEnumerator GetEnumerator() => ์ƒˆ๋กœ์šด NotImplementedException() ๋˜์ง€๊ธฐ;
}

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

```

๋˜ํ•œ ํ˜„์žฌ ์ œ์•ˆ๊ณผ ๋™์ผํ•œ ์„ฑ๋Šฅ ํŠน์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

| ๋ฐฉ๋ฒ• | ํ‰๊ท  | ์˜ค๋ฅ˜ | ํ‘œ์ค€ ๊ฐœ๋ฐœ | ์Šค์ผ€์ผ |
|------------ |---------:|---------:|---------:|--- ----:|
| ์ถ”๊ฐ€ | 405.0ns | 2.130ns | 1.889ns | 1.00 |
| ์ดˆ๊ธฐํ™” | 400.8ns | 4.821ns | 4.274ns | 0.99 |

์Šฌํ”„๊ฒŒ๋„ IEnumerable ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ๋งŒ์กฑ์Šค๋Ÿฝ๊ฒŒ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌํ˜„๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์†Œ ํ•ดํ‚น์ž…๋‹ˆ๋‹ค. ์ฆ‰, Obsolete ๋Š” foreach ์—์„œ๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ ค๋ฉด ์‹ค์ œ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‘˜์˜ MSIL์€ ๋ณธ์งˆ์ ์œผ๋กœ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

@jcdickinson ๋ฌธ์ œ๋ฅผ ์žก์•„์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. Collaborator ์ดˆ๋Œ€๋ฅผ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋ฝํ•  ๋•Œ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฌ๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๊ท€ํ•˜์—๊ฒŒ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ ๋™์•ˆ ๋‚˜ ์ž์‹ ์—๊ฒŒ ํ• ๋‹น).

์ „๋ฌธ๊ฐ€ ํŒ: ์ˆ˜๋ฝํ•˜๋ฉด GitHub์—์„œ ์ €์žฅ์†Œ์˜ ๋ชจ๋“  ์•Œ๋ฆผ(ํ•˜๋ฃจ 500๊ฐœ ์ด์ƒ)์— ๋Œ€ํ•ด ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋ชจ๋“  ๋ฉ˜์…˜ ๋ฐ ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋Š” "Not Watching"์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ตฌ๋…ํ–ˆ์Šต๋‹ˆ๋‹ค.

@jcdickinson , ๋‚˜๋Š” ์„ฑ๊ฐ€์‹  ๋ฐ˜๋ณต์„ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์— ํ™•์‹คํžˆ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค(์ดˆ๊ธฐํ™” ๊ตฌ๋ฌธ์— ๋Œ€ํ•ด ์‚ฌ๋žŒ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋Š๋‚„์ง€๋Š” ๋ชจ๋ฅด์ง€๋งŒ). ๋‚˜๋Š” ์œ ์ฐฝํ•จ์— ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์–ธ๊ธ‰ํ•œ ์„ฑ๋Šฅ ๋ฌธ์ œ
  2. Fluent ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ ๊ตฌ์กฐ์ฒด์˜ ๋ณต์‚ฌ๋ณธ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์„ ํ•˜๋‹ค๊ฐ€ ์‹ค์ˆ˜๋กœ ์ž…๋ ฅ์„ ์žƒ๋Š” ๊ฒƒ์€ ๋„ˆ๋ฌด ์‰ฝ์Šต๋‹ˆ๋‹ค.
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. Obsolete ๋ฉ”์‹œ์ง€์—์„œ 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 ๋ฒค์น˜๋งˆํ‚นํ•œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋˜๋Š” SpookilySharp nuget ํŒจํ‚ค์ง€๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” 2๋…„์˜ ์นจ์ฒด ์ดํ›„์— ๊ทธ ํ”„๋กœ์ ํŠธ์˜ ๋จผ์ง€๋ฅผ ํ„ธ์–ด๋‚ด๋ ค ํ•˜๊ณ  ์žˆ๊ณ  ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์„œ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

@JonHanna ๊ทธ๋Š” ์—ฌ๊ธฐ์— ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค: https://github.com/gimpf/Haschisch.Kastriert

@JonHanna , ๋ฒ”์šฉ ๋น„์•”ํ˜ธํ™” ํ•ด์‹ฑ API์—์„œ ๋ฌด์—‡์ด ์œ ์šฉํ•œ์ง€ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ง„ํ–‰๋˜๋Š”์ง€ ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

@morganbr ๊ทธ๋Ÿฌํ•œ API๋ฅผ ๋…ผ์˜ํ•  ์ ์ ˆํ•œ ํฌ๋Ÿผ์€ ์–ด๋””์ธ๊ฐ€์š”? ๋‚˜๋Š” ๊ทธ๋Ÿฌํ•œ API๊ฐ€ ๊ฐ€์žฅ ๋‚ฎ์€ ๊ณตํ†ต ๋ถ„๋ชจ ์ด์ƒ์œผ๋กœ ๊ตฌ์„ฑ๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๋ฉฐ, ์•„๋งˆ๋„ ์ข‹์€ API๋Š” ๋” ํฐ ๊ตฌ์กฐ์ฒด์˜ ํ–ฅ์ƒ๋œ JIT wrt ์ฒ˜๋ฆฌ๋„ ํ•„์š”๋กœ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ณ„๋„์˜ ๋ฌธ์ œ์—์„œ ๋” ์ž˜ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์— ๋Œ€ํ•ด ๋…ผ์˜...

@gimpf ๋‹น์‹ ์„ ์œ„ํ•ด ํ•˜๋‚˜๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ท๋„ท/corefx#25666

@morganbr - ์ด ์ปค๋ฐ‹์„ ํฌํ•จํ•  ํŒจํ‚ค์ง€ ์ด๋ฆ„ ๋ฐ ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@karelz , ํŒจํ‚ค์ง€/๋ฒ„์ „ ์ •๋ณด๋กœ @smitpatel ์„ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” .NET Core์˜ ๋งค์ผ ๋นŒ๋“œ๋ฅผ ์‹œ๋„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค - ๋‚˜๋Š” ๋‚ด์ผ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋‚˜๋Š” ๋‹น์‹ ์ด ๋‹จ์ˆœํžˆ ์˜์กดํ•  ์ˆ˜ ์žˆ๋Š” ํŒจํ‚ค์ง€๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ์ฐธ๊ฐ€์ž๋“ค์—๊ฒŒ ์งˆ๋ฌธํ•ฉ๋‹ˆ๋‹ค. Roslyn IDE๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ž˜์Šค/๊ตฌ์กฐ์ฒด์˜ ํ•„๋“œ/์†์„ฑ ์ง‘ํ•ฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ GetHashCode impl์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ ์‚ฌ๋žŒ๋“ค์€ https://github.com/dotnet/corefx/pull/25013 ์— ์ถ”๊ฐ€๋œ ์ƒˆ๋กœ์šด HashCode.Combine์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ผ๋ถ€ ์‚ฌ์šฉ์ž๋Š” ํ•ด๋‹น ์ฝ”๋“œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ ๊ทธ๋“ค์—๊ฒŒ ์ž‘๋™ํ•  GetHashCode๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

์ตœ๊ทผ์— ์šฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ํ˜•์‹์ด ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด ์•Œ๋ ค์กŒ์Šต๋‹ˆ๋‹ค. ์ฆ‰, VB๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์˜ค๋ฒ„ํ”Œ๋กœ ๊ฒ€์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํŒŒ์ผํ•˜๊ณ  impl์€ ์˜ค๋ฒ„ํ”Œ๋กœ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ๋˜ํ•œ VB๋Š” ์ฝ”๋“œ ์˜์—ญ์— ๋Œ€ํ•œ ์˜ค๋ฒ„ํ”Œ๋กœ ๊ฒ€์‚ฌ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•  ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ์ „์ฒด ์–ด์…ˆ๋ธ”๋ฆฌ์— ๋Œ€ํ•ด ์™„์ „ํžˆ ์ผœ์ ธ ์žˆ๊ฑฐ๋‚˜ ๊บผ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” impl์„ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๊ฒช์ง€ ์•Š๋Š” ํ˜•์‹์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ ์ƒ์„ฑ๋œ ์–‘์‹์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์‚ฌ์šฉ๋œ ํ•„๋“œ/์†์„ฑ๋‹น GetHashCode์˜ ํ•œ ์ค„/๋‘ ์ค„.
  2. ๋„˜์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  3. ํ•ฉ๋ฆฌ์ ์œผ๋กœ ์ข‹์€ ํ•ด์‹ฑ. ์šฐ๋ฆฌ๋Š” ๋†€๋ผ์šด ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋Œ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฏธ ๊ดœ์ฐฎ์€ ๊ฒƒ์œผ๋กœ ๊ฒ€์ฆ๋˜์—ˆ์œผ๋ฉฐ a + b + c + d ๋˜๋Š” a ^ b ^ c ^ d ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์—†๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.
  4. ์ฝ”๋“œ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ข…์†์„ฑ/์š”๊ตฌ ์‚ฌํ•ญ์ด ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, VB์— ๋Œ€ํ•œ ํ•œ ๊ฐ€์ง€ ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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 , ์‚ฌ์šฉ์ž ์ฝ”๋“œ์—์„œ ์ž์ฒด ํ•ด์‹œ ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ CRC32๊ฐ€ ํ…Œ์ด๋ธ” ์กฐํšŒ์™€ XOR์˜ ์กฐํ•ฉ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ฒ„ํ”Œ๋กœํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฐ์ˆ ์€ ์•„๋‹˜). ๊ทธ๋Ÿฌ๋‚˜ ๋ช‡ ๊ฐ€์ง€ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. CRC32๋Š” ์—”ํŠธ๋กœํ”ผ๊ฐ€ ํฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค(ํ•˜์ง€๋งŒ Roslyn์ด ์ง€๊ธˆ ๋ฐฉ์ถœํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์—ฌ์ „ํžˆ ๋” ๋‚˜์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค).
  2. 256 ํ•ญ๋ชฉ ์กฐํšŒ ํ…Œ์ด๋ธ”์„ ์ฝ”๋“œ ์–ด๋”˜๊ฐ€์— ๋„ฃ๊ฑฐ๋‚˜ ์กฐํšŒ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ๋ฐฉ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•„์ง ํ•˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด XXHash๊ฐ€ ํ›จ์”ฌ ๋” ๋‚˜์„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— HashCode ์œ ํ˜•์„ ๊ฐ์ง€ํ•˜๊ณ  ๊ฐ€๋Šฅํ•˜๋ฉด ์ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@morganbr ์ฐธ์กฐ https://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 ํ•ญ๋ชฉ ์กฐํšŒ ํ…Œ์ด๋ธ”์„ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์™„์ „ํžˆ ๋ง›์ด ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค :)

ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์ฝ”๋“œ๋„ ๋ถˆ์พŒํ•œ๊ฐ€์š”? ์ ์–ด๋„ Wikipedia์˜ ์˜ˆ ๋ฅผ ๋ณด๋ฉด ์ฝ”๋“œ๊ฐ€ ๋งŽ์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ์—ฌ์ „ํžˆ ์‚ฌ์šฉ์ž ์†Œ์Šค์˜ ์–ด๋”˜๊ฐ€์— ์žˆ์–ด์•ผ ํ•จ).

์ฐธ์กฐ๋œ ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ๋•Œ (ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•œ) ์ปดํŒŒ์ผ๋Ÿฌ ์†์„ฑ ํด๋ž˜์Šค ์ •์˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Roslyn์ด (IL๊ณผ ํ•จ๊ป˜) HashCode ์†Œ์Šค๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ๋”์ฐํ• ๊นŒ์š”?

์ฐธ์กฐ๋œ ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ๋•Œ Roslyn์ด (ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•œ) ์ปดํŒŒ์ผ๋Ÿฌ ์†์„ฑ ํด๋ž˜์Šค ์ •์˜๋กœ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ HashCode ์†Œ์Šค๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ๋”์ฐํ• ๊นŒ์š”?

  1. HashCode ์†Œ์Šค์— ์˜ค๋ฒ„ํ”Œ๋กœ ๋™์ž‘์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?
  2. HashCode ์†Œ์Šค๋ฅผ ํ›‘์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์•„๋‹Œ ์‚ฌ์†Œํ•œ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ํ”„๋กœ์ ํŠธ์— ๋ชจ๋“  ์žก๋™์‚ฌ๋‹ˆ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ๊ฝค ๋ฌด๊ฑฐ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

VB์—์„œ ์˜ค๋ฒ„ํ”Œ๋กœ ์ˆ˜ํ•™์ด ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋Š” ์‚ฌ์‹ค์— ๋†€๋ž์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ตœ์†Œํ•œ ๋‘ ๊ฐ’์„ ํ•จ๊ป˜ ํ•ด์‹ฑํ•˜๋”๋ผ๋„ ๋‹ค์Œ์„ ์ƒ์„ฑํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

```c#
var hc1 = (๋‹จ์œ„)(๊ฐ’1?.GetHashCode() ?? 0); // ์˜ค๋ฒ„ํ”Œ๋กœ ๊ฐ€๋Šฅ
var hc2 = (๋‹จ์œ„)(๊ฐ’2?.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 ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ๋”์ฐํ•œ ์ผ์ž…๋‹ˆ๊นŒ

์ด ์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ์˜ˆ์ƒํ•˜์‹ญ๋‹ˆ๊นŒ? ๊ณ ๊ฐ์€ ๋ฌด์—‡์„ ์ž‘์„ฑํ•˜๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ๋ฌด์—‡์„ ํ•ฉ๋‹ˆ๊นŒ?

๋˜ํ•œ ์ด ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ .Net์ด ์˜ค๋ฒ„ํ”Œ๋กœ ์—†์ด uint์—์„œ int32๋กœ(๋˜๋Š” ๊ทธ ๋ฐ˜๋Œ€๋กœ) ๋ณ€ํ™˜ํ•˜๋Š” ํ‘œ๋ฉด API์— ์ด๋ฏธ ๋…ธ์ถœ๋œ ๊ณต๊ฐœ ๋„์šฐ๋ฏธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์˜ค๋ฒ„ํ”Œ๋กœ ์—†์ด ์œ ํ˜• ์‚ฌ์ด๋ฅผ ์ด๋™ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์— ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ VB ๋ฒ„์ „์„ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์ฝ”๋“œ๋„ ๋ถˆ์พŒํ•œ๊ฐ€์š”?

๋‚˜๋Š” ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ œ ๋ง์€, ์ด๊ฒƒ์„ ๊ณ ๊ฐ์˜ ๊ด€์ ์—์„œ ์ƒ๊ฐํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋“ค์€ ๋‹จ์ง€ ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž์ฒด ํฌํ•จ๋˜๊ณ  ํ•ฉ๋ฆฌ์ ์ธ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ดœ์ฐฎ์€ GetHashCode ๋ฉ”์†Œ๋“œ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ณ  ๋ณด์กฐ ์“ฐ๋ ˆ๊ธฐ๋กœ ์ฝ”๋“œ๋ฅผ ๋ถ€ํ’€๋ฆฌ๋Š” ๊ฒƒ์€ ๊ฝค ๋ถˆ์พŒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. C# ๊ฒฝํ—˜์ด ๊ดœ์ฐฎ์„ ๊ฒƒ์ด๋ผ๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ๋˜ํ•œ ๊ฝค ๋‚˜์ฉ๋‹ˆ๋‹ค.

์„œ๋ช…๋œ 64๋น„ํŠธ ์œ ํ˜•๊ณผ ์„œ๋ช…๋˜์ง€ ์•Š์€ 64๋น„ํŠธ ์œ ํ˜•์˜ ์ผ๋ถ€ ์กฐํ•ฉ์œผ๋กœ ๋˜๋Š” ๊ทธ๋กœ๋ถ€ํ„ฐ ์บ์ŠคํŒ…ํ•˜์—ฌ ๋Œ€๋žต์ ์œผ๋กœ ์˜ฌ๋ฐ”๋ฅธ ์˜ค๋ฒ„ํ”Œ๋กœ ๋™์ž‘์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๊ฒƒ(ํ…Œ์ŠคํŠธ๋˜์ง€ ์•Š์•˜์œผ๋ฉฐ VB ์บ์ŠคํŒ… ๊ตฌ๋ฌธ์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค):

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

๋‹ค์Œ์ด ์˜ค๋ฒ„ํ”Œ๋กœ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

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

๋˜๋Š” ๊ทธ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์ตœ์ข… (int32) ์บ์ŠคํŠธ?

์˜ค๋ฒ„ํ”Œ๋กœ ํ™•์ธ ๋ณ€ํ™˜ ์ž‘์—…์„ ์‚ฌ์šฉํ•  ์ค„์€ ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค. ์บ์ŠคํŒ…ํ•˜๊ธฐ ์ „์— 32๋น„ํŠธ๋กœ ๋งˆ์Šคํ‚นํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

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

uint32.Max ๊ฐ’๋„ Int32๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์˜ค๋ฒ„ํ”Œ๋กœ๋˜๋ฏ€๋กœ ์•„๋งˆ๋„ 31๋น„ํŠธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. :)

๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ถ”์•…ํ•˜์ง€๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค :) ์ด ์ฝ”๋“œ์—๋Š” ๋งŽ์€ ์บ์ŠคํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์ธ. ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์†”๋ฃจ์…˜์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  ์šฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ•ต์‹ฌ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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์ด๊ณ  ์ƒ์ˆ˜๊ฐ€ ๊ทธ๋ณด๋‹ค ํ›จ์”ฌ ์ž‘๊ธฐ ๋•Œ๋ฌธ์—) ์ƒ์œ„ ๋น„ํŠธ๋ฅผ 0์œผ๋กœ ๋งˆ์Šคํ‚นํ•˜๋ฏ€๋กœ 31๋น„ํŠธ ํ•ด์‹œ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์ƒ์œ„ ๋น„ํŠธ๋ฅผ ์ผœ์ง„ ์ƒํƒœ๋กœ ๋‘๋Š” ๊ฒƒ์ด ์˜ค๋ฒ„ํ”Œ๋กœ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๊นŒ?

@CyrusNajmabadi hashCode A๋Š” Long ๋กœ ์–ด๋””์„œ๋“  0์—์„œ ํ•  ์ˆ˜ Integer.MaxValue . ์™œ ๋‚ด๊ฐ€ ์ด๊ฒƒ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

image

๊ทธ๋Ÿฌ๋‚˜ ์•„๋‹ˆ์š”, ์‹ค์ œ๋กœ ๋„˜์น  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

Btw- ์ฐจ์„ ์ฑ… ํ•ด์‹œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค Roslyn์ด NuGet ํŒจํ‚ค์ง€๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ƒ์œ„ ๋น„ํŠธ๋ฅผ 0์œผ๋กœ ๋งˆ์Šคํ‚นํ•˜๋ฏ€๋กœ 31๋น„ํŠธ ํ•ด์‹œ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์ƒ์œ„ ๋น„ํŠธ๋ฅผ ์ผœ์ง„ ์ƒํƒœ๋กœ ๋‘๋Š” ๊ฒƒ์ด ์˜ค๋ฒ„ํ”Œ๋กœ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๊นŒ?

๊ทธ๊ฑด ์ข‹์€ ์ง€์ ์ด์•ผ. ๋‚˜๋Š” ๋‹จ์œ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ long์—์„œ uint๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด ๋ถ€ํ˜ธ ๋น„ํŠธ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•„์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๋ชจ๋‘ ๋ถ€ํ˜ธ ์žˆ๋Š” ์ˆ˜ํ•™์ด๋ฏ€๋กœ ๊ฐ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•œ ํ›„ ํ•˜์œ„ 32๋น„ํŠธ๋งŒ ์œ ์ง€ํ•˜๋„๋ก 0xffffffff์— ๋Œ€ํ•ด ๋งˆ์Šคํฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ฐจ์„ ์ฑ… ํ•ด์‹œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค 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)

ํฅ๋ฏธ๋กœ์šด์ด ์ž‘ํ’ˆ์€ ํŠนํžˆ ํ˜ธ์ถœ .GetHashCode() ์— ์˜ํ•ด ์ƒ์„ฑ ๋œ Int64 ๊ฐ’์— (hashCode * -1521134295 + a.GetHashCode()) . ์ด 64๋น„ํŠธ ๊ฐ’์— ๋Œ€ํ•ด .GetHashCode๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์šฐ๋ฆฌ์˜ ์š”๊ตฌ์— ๋งž๋Š” ๋‘ ๊ฐ€์ง€ ์ข‹์€ ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ์งธ, hashCode๊ฐ€ ํ•ฉ๋ฒ•์ ์ธ int32 ๊ฐ’๋งŒ ์ €์žฅํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค(์ตœ์ข… ๋ฐ˜ํ™˜ ์บ์ŠคํŠธ๋ฅผ ํ•ญ์ƒ ์•ˆ์ „ํ•˜๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ). ๋‘˜์งธ, ์ž‘์—… ์ค‘์ธ int64 ์ž„์‹œ ๊ฐ’์˜ ์ƒ์œ„ 32๋น„ํŠธ์—์„œ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ์žƒ์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

@CyrusNajmabadi ์‹ค์ œ๋กœ ํŒจํ‚ค์ง€ ์„ค์น˜๋ฅผ ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์ด ์ œ๊ฐ€ ์งˆ๋ฌธํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ•ด์•ผ ํ•˜๋Š” ์ผ์—์„œ ๊ตฌํ•ด์ค๋‹ˆ๋‹ค.

HashCode๋ฅผ ์ž…๋ ฅํ•˜๋ฉด MS nuget ํŒจํ‚ค์ง€์— System.HashCode๊ฐ€ ์ œ๊ณต๋˜๋ฉด Roslyn์ด ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” GetHashCode ์˜ค๋ฒ„๋กœ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋™์ผํ•œ ์ž‘์—…์œผ๋กœ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ ์„ ํƒ์ด ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ข…์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ•์ œ๋กœ ์ˆ˜ํ–‰ํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” ๋งค์šฐ ๋ฌด๊ฑฐ์šด ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ด๋Ÿฌํ•œ ์„ ํƒ์„ ํ•  ์ ์ ˆํ•œ ์‹œ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ IDE๋Š” ์ด๋ฅผ ์กด์ค‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๋ชจ๋“  ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์ทจํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์ด์—ˆ๊ณ  ์‚ฌ๋žŒ๋“ค์ด ์ข‹์•„ํ•˜๋Š” ๊ฑด๊ฐ•ํ•œ ๋ฐฉ์‹์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ : ์ฐธ์กฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์ด API๊ฐ€ ํฌํ•จ๋œ nuget ํŒจํ‚ค์ง€๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๊ตฌํ˜„์€ System.Private.CoreLib.dll์— ์žˆ์œผ๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„ ํŒจํ‚ค์ง€์˜ ์ผ๋ถ€๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ๊ณ„์•ฝ์€ System.Runtime.dll์ž…๋‹ˆ๋‹ค.

ํ™•์ธ. ์ด ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ€ ์ตœ์‹  ๋Œ€์ƒ ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ์ด๋™ํ•  ๋•Œ ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์ข…๋ฅ˜์˜ ์ผ์€ ๋‚ด๊ฐ€ ์‚ฌ์šฉ์ž์˜ ํ”„๋กœ์ ํŠธ์— "Equals+hashcode ์ƒ์„ฑ"์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ๋‹จ๊ณ„๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰