今天项目(C#项目)中遇到了一个性能问题,在对一个10万字左右文本解析时速度特别慢,用Profiler调查了一下原来大多时间都用在了String.EndsWith这个方法上。 大家现在看下面一段程序。
var sb = new StringBuilder(100000);
for (var i = 0; i < 10000; i++)
{
sb.Append("ABCDEFGHIJ");
}
var text = sb.ToString();
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < 10000; i++)
{
var b = text.EndsWith("AAAA");
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
大家觉得这段程序大概要执行多长时间?
在我的机器上:36782 毫秒
大家再看这段代码
var sb = new StringBuilder(100000);
for (var i = 0; i < 10000; i++)
{
sb.Append("ABCDEFGHIJ");
}
var text = sb.ToString();
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < 10000; i++)
{
var b = text.EndsWith("AAAA", StringComparison.Ordinal);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
仅仅加了一个StringComparison.Ordinal, 执行时间是0,也就是不到1毫秒。
之前一直做java的项目,对于java里的String的endsWith出了比较字符串以外没有任何悬念。所以习惯性的在C#里也这样用。 但是在C#里,StringComparison.Ordinal才是常规用法。因为:
1. 用了它EndsWith会非常快
2. 一般情况下就是你想要的比较方式
使用StringComparison.Ordinal的比较方式就是我们常用的把字符当纯数字的比较方式。
如果不加这个参数, String的EndsWith的比较方式是culture-sensitive的,相当于EndsWith(str, StringComparison.CurrentCulture)。 这个是什么概念呢。 简单来讲就是某些语言上,虽然字符不同但是在语言上是相同的。
例如在德语环境下:
static void Main(string[] args)
{
Console.WriteLine("Grüße".EndsWith("sse", StringComparison.Ordinal));
Console.WriteLine("Grüße".EndsWith("sse", StringComparison.CurrentCulture));
Console.WriteLine("Grüße".EndsWith("sse", StringComparison.InvariantCulture));
Console.WriteLine("Grüße".EndsWith("sse"));
}
得到的结果是:
False
True
True
True