Array.ForEach()与C#中的循环标准相比如何?

时间:2010-03-25 19:01:27

标签: c# .net performance

作为一名C程序员,我可以输入:

memset( byte_array, '0xFF' );

并获取一个填充'FF'字符的字节数组。所以,我一直在寻找替代品:

for (int i=0; i < byteArray.Length; i++)
{
    byteArray[i] = 0xFF;
}

最近,我一直在使用一些新的C#功能,并且一直在使用这种方法:

Array.ForEach<byte>(byteArray, b => b = 0xFF);

当然,第二种方法似乎更清晰,更容易看到,但性能与使用第一种方法相比如何呢?我是否通过使用Linq和泛型来引入不必要的开销?

谢谢, 戴夫

7 个答案:

答案 0 :(得分:7)

Array.ForEach<byte>(byteArray, b => b = 0xFF);

这没有任何作用。它将每个字节的副本设置为0xFF,它永远不会在数组中设置。

为了更简单地执行此操作,您可以尝试

Enumerable.Repeat((byte)0xFF, someCount).ToArray();

初始化数组

重复肯定会慢于你的for循环。根据CAbbott在评论中发布的链接,在一个拥有超过一百万个项目的阵列上,它慢了大约10.5秒(12.38对1.7),但如果你只用一小部分做了几次就没那么大的差别阵列。

你可以编写一个比Repeat和ToArray更快的简单方法,因为你可以在开始填充之前知道数组的长度。

  public static T[] GetPreFilledArray<T>(T fillItem, int count)
  {
       var result = new T[count];
       for(int i =0; i < count; i++)
       {
           result[i] = fillItem;
       }
       return result;
  }

  byte[] byteArray = GetPreFilledArray((byte)0xFF, 1000);

这应该是一个非常快速的选择,因为它基本上就是你现在所做的。

答案 1 :(得分:4)

第二种方法使用委托来设置每个字节,这意味着对数组中的每个字节都有一个方法调用。设置一个字节只需要很多开销。

另一方面,普通循环由编译器进行了相当好的优化。它将确定索引不能在数组之外,因此它将跳过边界检查。

澄清一下:你根本就没有使用LINQ。 ForEach方法是Array类中的一个方法,它早于添加LINQ。

答案 2 :(得分:1)

当我想要memset / memcpy类型行为时,我倾向于使用

Buffer.BlockCopy。我会测量性能并使用反射器之类的东西。可能是内部语言调用内置类,而内置类又是MEMCPY和MEMSET的瘦包装。

答案 3 :(得分:1)

如果您的表现类似于发布CAbott所引用问题的人,您可能需要查看my answer I just posted there

答案 4 :(得分:0)

除非你在非常严格的表现操作中这样做,否则你不会遇到问题。关于foreach调用与索引迭代有很多基准测试,差异很小。

当然,你总是可以自己对它进行基准测试......

答案 5 :(得分:0)

我不认为仿制药会对性能产生不利影响。它们主要在编译时处理,它们的一般目的是消除在对象和所需类型之间进行投射的需要,这种情况最坏的影响可以忽略不计,最多可以带来可衡量的性能提升。

就LINQ而言,我不确定它可以有什么性能影响。

最终,初始化是一项次要任务,性能影响无关紧要。

答案 6 :(得分:0)

如果你将它们放在一个关键的执行路径中,我发现Array.ForEach要比for或foreach循环慢得多。但是,除非您是框架/库开发人员或实际需要初始化数百万个数组,否则我根本不担心性能。通过在其他地方进行优化,您很可能获得更多收益。