Mic*_*ael 3 c# linq performance
我有两个方法接受一个字符串并删除任何"无效"字符(哈希集中包含的字符).一种方法使用Linq.Where,另一种方法使用循环w/char数组.
Linq方法需要几乎两倍的长度(208756.9滴答)与循环(108688.2滴答)
LINQ:
string Linq(string field)
{
var c = field.Where(p => !hashChar.Contains(p));
return new string(c.ToArray());
}
Run Code Online (Sandbox Code Playgroud)
环:
string CharArray(string field)
{
char[] c = new char[field.Length];
int count = 0;
for (int i = 0; i < field.Length; i++)
if (!hashChar.Contains(field[i]))
{
c[count] = field[i];
count++;
}
if (count == 0)
return field;
char[] f = new char[count];
Buffer.BlockCopy(c, 0, f, 0, count * sizeof(char));
return new string(f);
}
Run Code Online (Sandbox Code Playgroud)
我的期望是LINQ会击败或者至少可以与循环方法相媲美.循环方法甚至没有优化.我必须在这里遗漏一些东西.
Linq.Where是如何在幕后工作的,为什么它会失去我的方法?
如果Mono 的源代码ToArray是任何指示,那么您的实现会获胜,因为它执行的分配更少(向下滚动到第2874行以查看方法).
与LINQ的许多方法一样,该ToArray方法包含用于集合和其他可枚举的单独代码路径:
TSource[] array;
var collection = source as ICollection<TSource>;
if (collection != null) {
...
return array;
}
Run Code Online (Sandbox Code Playgroud)
在你的情况下,不采用这个分支,所以代码进入这个循环:
int pos = 0;
array = EmptyOf<TSource>.Instance;
foreach (var element in source) {
if (pos == array.Length) {
if (pos == 0)
array = new TSource [4];
else
// If the number of returned character is significant,
// this method will be called multiple times
Array.Resize (ref array, pos * 2);
}
array[pos++] = element;
}
if (pos != array.Length)
Array.Resize (ref array, pos);
return array;
Run Code Online (Sandbox Code Playgroud)
如您所见,LINQ的版本可能会多次分配和重新分配数组.另一方面,您的实现只进行两次分配 - 最大尺寸的前期分配,以及复制数据的最后一次分配.这就是为什么你的代码更快.