DaveN59
DaveN59

Reputation: 3728

How does Array.ForEach() compare to standard for loop in C#?

I pine for the days when, as a C programmer, I could type:

memset( byte_array, '0xFF' );

and get a byte array filled with 'FF' characters. So, I have been looking for a replacement for this:

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

Lately, I have been using some of the new C# features and have been using this approach instead:

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

Granted, the second approach seems cleaner and is easier on the eye, but how does the performance compare to using the first approach? Am I introducing needless overhead by using Linq and generics?

Thanks, Dave

Upvotes: 5

Views: 8853

Answers (7)

Mike
Mike

Reputation: 1568

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

This doesn't do anything. It's setting a copy of each byte to 0xFF, it never gets set in the array.

For an easier way to do this, you could try

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

to initialize your array

Repeat will definitely be slower than your for loop. According to the link posted by CAbbott in a comment, it's about 10.5 seconds slower (12.38 vs 1.7) on an array with over a million items, but that isn't a big difference if you're only doing it a few times with small arrays.

You could write a simple method that will be quicker than Repeat and ToArray because you can know the length of the array before you start filling it.

  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);

That should be a pretty quick option, as it's basically what you're doing now.

Upvotes: 7

Lucero
Lucero

Reputation: 60276

If you're after performance like the guy who posted the question to which CAbott referred to, you might want to have a look at my answer I just posted there.

Upvotes: 1

Morten Mertner
Morten Mertner

Reputation: 9474

I've found Array.ForEach to be significantly slower than a for or foreach loop if you have them in a critical execution path. However, unless you are a framework/library developer or actually need to initialize millions of arrays I wouldn't worry about performance at all. It's very likely that you can gain much more by optimizing elsewhere.

Upvotes: 0

Digicoder
Digicoder

Reputation: 1875

Buffer.BlockCopy is what I tend to use when I want memset/memcpy type behavior. I would measure the performance and use something like reflector. It may be that internally the language calls the built-in classes, which in turn are thin wrappers around MEMCPY and MEMSET.

Upvotes: 1

Guffa
Guffa

Reputation: 700910

The second method uses a delegate to set each byte, this means that there is a method call for every byte in the array. That's a lot of overhead just to set a byte.

The plain loop on the other hand gets optimised rather well by the compiler. It will determine that the index can not be outside the array, so it will skip the bounds checking.

To clarify: You are not using LINQ at all. The ForEach method is a method in the Array class, and it predates the addition of LINQ.

Upvotes: 4

Spencer Ruport
Spencer Ruport

Reputation: 35117

I don't think generics can ever be a detriment to performance. They're primarily dealt with at compile time and their general purpose is to remove the need for casting between object and the desired type which will at worst have a negligible effect and at best result in a measurable performance gain.

As far as LINQ I'm not sure what performance effects it can have.

Ultimately though, the initializations are such a minor task the performance effects are going to be nothing worth your concern.

Upvotes: 0

Randolpho
Randolpho

Reputation: 56448

Unless you're doing this during very performance-critcal operation, you're not gonna have a problem. There are numerous benchmarks out there regarding foreach calls vs indexed iteration, and the difference is minimal.

Of course, you could always benchmark it yourself...

Upvotes: 0

Related Questions