string s = "abcabcabcabcabc";
var foundIndexes = new List<int>();
问题来自讨论here。我只是想知道
这怎么可能:
for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))
foundIndexes.Add(i);
比这更好:
for (int i = 0; i < s.Length; i++)
if (s[i] == 'a') foundIndexes.Add(i);
编辑:性能增益的来源是什么?
答案 0 :(得分:2)
我没有注意到使用IndexOf
比直接循环更快。老实说,我不知道它是怎么回事,因为在这两种情况下都需要检查每个角色。我最初的结果如下:
Found by loop, 974 ms
Found by IndexOf 1144 ms
编辑:经过几次运行后,我注意到你必须运行发布(即优化)才能看到上面的结果。没有优化,for循环确实更慢。
基准代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;
using System.Diagnostics;
namespace Test
{
public class Program
{
public static void Main(string[] args)
{
const string target = "abbbdbsdbsbbdbsabdbsabaababababafhdfhffadfd";
// Jit methods
TimeMethod(FoundIndexesLoop, target, 1);
TimeMethod(FoundIndexesIndexOf, target, 1);
Console.WriteLine("Found by loop, {0} ms", TimeMethod(FoundIndexesLoop, target, 2000000));
Console.WriteLine("Found by IndexOf {0} ms", TimeMethod(FoundIndexesIndexOf, target, 2000000));
}
private static long TimeMethod(Func<string, List<int>> method, string input, int reps)
{
var stopwatch = Stopwatch.StartNew();
List<int> result = null;
for(int i = 0; i < reps; i++)
{
result = method(input);
}
stopwatch.Stop();
TextWriter.Null.Write(result);
return stopwatch.ElapsedMilliseconds;
}
private static List<int> FoundIndexesIndexOf(string s)
{
List<int> indexes = new List<int>();
for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))
{
// for loop end when i=-1 ('a' not found)
indexes.Add(i);
}
return indexes;
}
private static List<int> FoundIndexesLoop(string s)
{
var indexes = new List<int>();
for (int i = 0; i < s.Length; i++)
{
if (s[i] == 'a')
indexes.Add(i);
}
return indexes;
}
}
}
答案 1 :(得分:0)
IndexOf(char value, int startIndex)
标有以下属性:[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
。
此外,此方法的实现很可能以许多其他方式进行优化,可能使用不安全的代码,或使用更多“本机”技术,例如,使用本机FindNLSString
Win32函数。