当前位置:  开发笔记 > 编程语言 > 正文

静态字符串[]的C#性能包含()(slooooow)与==运算符

如何解决《静态字符串[]的C#性能包含()(slooooow)与==运算符》经验,为你挑选了3个好方法。

只是一个快速查询:我有一段代码将一个字符串与一长串值进行比较,例如

if(str == "string1" || str == "string2" || str == "string3" || str == "string4".
     DoSomething();

代码清晰度和可维护性的兴趣我把它改成了

public static string[] strValues = { "String1", "String2", "String3", "String4"};
...
if(strValues.Contains(str)
    DoSomething();

只发现代码执行时间从2.5秒到6.8秒(执行大约200,000次).
我当然明白了一个轻微的表现权衡,但300%?
无论如何,我可以不同地定义静态字符串以提高性能?
干杯.



1> Rusty..:

据透露..

使用:

private static HashSet strHashSet = new HashSet() 
{ "0string", "1string", "2string", "3string", "4string", "5string", 
  "6string", "7string", "8string", "9string", "Astring", "Bstring" };

private static List strList = strHashSet.ToList();
private static string[] strArray = strList.ToArray();
private static Dictionary strHashDict = strHashSet.ToDictionary(h => h.GetHashCode());
private static Dictionary strDict = strHashSet.ToDictionary(h => h);

// Only one test uses this method.
private static bool ExistsInList(string str)
{
  return strHashDict.ContainsKey(str.GetHashCode());
}

检查列表中的第一个和最后一个字符串,然后检查不在列表中的字符串:"xstring"执行500,000次迭代,所有时间都以毫秒为单位.

1.A Test: result = (str == "0string" || str == "1string" ...
[storage var]          [first]:[ last ]:[ none ]:[average]
strArray                 3.78 :  45.90 :  57.77 :  35.82

2.A Test: ExistsInList(string);
[storage var]          [first]:[ last ]:[ none ]:[average]
none                    36.14 :  28.97 :  24.02 :  29.71

3.A Test: .ContainsKey(string.GetHashCode());
[storage var]          [first]:[ last ]:[ none ]:[average]
strHashDict             34.86 :  28.41 :  21.46 :  28.24

4.A Test: .ContainsKey(string);
[storage var]          [first]:[ last ]:[ none ]:[average]
strDict                 38.99 :  32.34 :  22.75 :  31.36

5.A Test: .Contains(string);
[storage var]          [first]:[ last ]:[ none ]:[average]
strHashSet              39.54 :  34.78 :  24.17 :  32.83
strList                 23.36 : 122.07 : 127.38 :  90.94
strArray               350.34 : 426.29 : 426.05 : 400.90

6.A Test: .Any(p => p == string);
[storage var]          [first]:[ last ]:[ none ]:[average]
strHashSet              75.70 : 331.38 : 339.40 : 248.82
strList                 72.51 : 305.00 : 319.29 : 232.26
strArray                38.49 : 213.63 : 227.13 : 159.75

当我们更改列表中的字符串时,会产生有趣的(如果不是意外的)结果:

private static HashSet strHashSet = new HashSet() 
{ "string00", "string01", "string02", "string03", "string04", "string05", 
  "string06", "string07", "string08", "string09", "string10", "string11" };

用"string99"作为无检查.

1.B Test: result = (str == "string00" || str == "string01" ...
[storage var]          [first]:[ last ]:[ none ]:[average]
strArray                85.45 :  87.06 :  91.82 :  88.11

2.B Test: ExistsInList(string);
[storage var]          [first]:[ last ]:[ none ]:[average]
none                    30.12 :  27.97 :  21.36 :  26.48

3.B Test: .ContainsKey(string.GetHashCode());
[storage var]          [first]:[ last ]:[ none ]:[average]
strHashDict             32.51 :  28.00 :  20.83 :  27.11

4.B Test: .ContainsKey(string);
[storage var]          [first]:[ last ]:[ none ]:[average]
strDict                 36.45 :  32.13 :  22.39 :  30.32

5.B Test: .Contains(string);
[storage var]          [first]:[ last ]:[ none ]:[average]
strHashSet              37.29 :  34.33 :  23.56 :  31.73
strList                 23.34 : 147.75 : 153.04 : 108.04
strArray               349.62 : 460.19 : 459.99 : 423.26

6.B Test: .Any(p => p == string);
[storage var]          [first]:[ last ]:[ none ]:[average]
strHashSet              76.26 : 355.09 : 361.31 : 264.22
strList                 70.20 : 332.33 : 341.79 : 248.11
strArray                37.23 : 234.70 : 251.81 : 174.58

对于案例A和B看起来像测试2和3具有优势.

但是,HashSet.Contains(字符串)非常高效,不受列表内容的影响,并且具有清晰的语法......可能是最佳选择.

是的,这是真的,我没有生命.



2> Mark Byers..:

您尝试过的两种方法都具有O(n)性能,因此当您添加更多字符串时它们会变慢.如果您使用的是.NET 3.5或更高版本,那么您可以尝试使用HashSet替代版本并在应用程序开始时将其初始化一次.然后,您可以获得大约O(1)个查找.

对于.NET v2.0,您可以HashSet使用a 来模拟a Dictionary并使用ContainsKey而不使用该值.


对不起,你有点不对劲.我认为Framework 1.x最好的是`System.Collections.Hashtable`.因为1.x没有泛型!

3> Stephen Clea..:

你在生产代码中实际运行了200,000次吗?如果是这样,您可能希望将哈希检查视为更快的否定检查.

如果200,000次只是为了说明差异,那我就不用担心了.它的时间仅增加0.02毫秒.

Contains比测试静态字符串更通用,因此存在少量开销.除非这个代码是Mark提到的瓶颈,否则不值得优化.CS中有一句名言:"过早优化是所有邪恶的根源." 报价不太准确,但它提醒了最终的优化指南:先测量.


我发现*清晰可读的代码*比将大量工作投入微优化更加节省时间,微优化在实际场景中使用时具有不可察觉的小运行时影响.
推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有