为什么不区分大小写的 HashSet<T> 性能如此糟糕

hIp*_*pPy 0 c# performance hashset

为什么HashSet<string>(StringComparer.InvariantCultureIgnoreCase)( Perf_HashSet_CaseInsensitive) 的表现如此糟糕?解决Perf_HashSet方法的性能相对而言提高了 20 倍。

// perf Contains(): 1M iterations, 25 size (unsuccessful lookup)
Test                         Duration (ms)
Perf_HashSet                            43 <-
Perf_Dictionary                         49 
Perf_HybridDictionary                   63 
Perf_ListDictionary                    223 
Perf_List                              225 
Perf_HashSet_CaseInsensitive           903 <-
Run Code Online (Sandbox Code Playgroud)

代码:

// perf Contains(): 1M iterations, 25 size (unsuccessful lookup)
Test                         Duration (ms)
Perf_HashSet                            43 <-
Perf_Dictionary                         49 
Perf_HybridDictionary                   63 
Perf_ListDictionary                    223 
Perf_List                              225 
Perf_HashSet_CaseInsensitive           903 <-
Run Code Online (Sandbox Code Playgroud)

Swe*_*per 5

性能差异如此之大的主要原因是,您对不区分大小写的哈希集使用了区域性敏感的比较,而区分大小写的哈希集则使用序数。

\n

在不向哈希集传递任何相等比较器的情况下,哈希集使用该类型的默认相等比较器来调用该Equals方法。请注意String.Equals

\n
\n

执行序数(区分大小写且不区分区域性)比较。

\n
\n

然而StringComparer.InvariantCultureIgnoreCase

\n
\n

使用不变区域性的单词比较规则执行不区分大小写的字符串比较。

\n
\n

值得注意的是,“文化不变”与“文化不敏感”或“序数”不同:

\n

Console.WriteLine(StringComparer.InvariantCultureIgnoreCase.Equals(\n"ss", "\xc3\x9f")); // true\nConsole.WriteLine(StringComparer.OrdinalIgnoreCase.Equals(\n"ss", "\xc3\x9f")); // 错误的

\n

不变的文化仍然有排序规则,查找和应用这些规则需要时间。

\n

更改InvariantCultureIgnoreCaseOrdinalIgnoreCase应该会使执行时间几乎相同。正如评论所指出的那样,这并不意味着您的基准测试不存在其他问题。

\n