有办法改善这个吗:
private static int CountNewlines(string s)
{
int len = s.Length;
int c = 0;
for (int i=0; i < len; i++)
{
if (s[i] == '\n') c++;
}
return c;
}
我特别关注字符串的Item访问器。 不确定它是否像C/C++一样只是指针算术。
有办法改善这个吗:
private static int CountNewlines(string s)
{
int len = s.Length;
int c = 0;
for (int i=0; i < len; i++)
{
if (s[i] == '\n') c++;
}
return c;
}
我特别关注字符串的Item访问器。 不确定它是否像C/C++一样只是指针算术。
我测试了这些实现
private static int Count1(string s)
{
int len = s.Length;
int c = 0;
for (int i=0; i < len; i++)
{
if (s[i] == '\n') c++;
}
return c+1;
}
private static int Count2(string s)
{
int count = -1;
int index = -1;
do
{
count++;
index = s.IndexOf('\n', index + 1);
}
while (index != -1);
return count+1;
}
private static int Count3(string s)
{
return s.Count( c => c == '\n' ) + 1;
}
private static int Count4(string s)
{
int n = 0;
foreach( var c in s )
{
if ( c == '\n' ) n++;
}
return n+1;
}
private static int Count5(string s)
{
var a = s.ToCharArray();
int c = 0;
for (int i=0; i < a.Length; i++)
{
if (a[i]=='\n') c++;
}
return c+1;
}
这是我的100,000次迭代计时结果,适用于一个长度约为25k的字符串。数值越小,速度越快。
Time Factor
Count1 4.8581503 1.4
Count2 4.1406059 1.2
Count3 45.3614124 13.4
Count4 3.3896130 1.0
Count5 5.9304543 1.7
出乎我的意料,通过测试,我发现使用 Enumerator 实现是最快的,而且速度相比其他实现方式要快20%。不管函数执行顺序如何,结果都是可重复的。我还使用了预热阶段来确保消除瞬态影响(例如 JIT 等)。
这是在发布构建(/optimize+)下进行的测试。
我非常确定这种方法不会比将字符串转换为字节并检查那些字节要慢,如果不是更快的话。String类应该有高度优化。
如果这是一个大字符串,也许通过几个线程的并行执行可以使事情变得更快 :-)
这可能是最有效的选择 - 项目访问器在内部进行了优化,您可以将其视为执行指针算术运算。
嗯,String
实现了 IEnumerable<char>
,所以我肯定会尝试:
s.Count( c => c == '\n' )
虽然这看起来很好,但原始方法快了30倍 :)
我还没有放弃IEnumerable,所以我也尝试过:
int n = 0;
foreach( var c in s )
{
if ( c == '\n' ) n++;
}
return n;
看起来速度与原始方法一样快。