views:

251

answers:

7

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

A: 

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...

Randolpho
A: 

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.

Spencer Ruport
+4  A: 

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.

Guffa
+5  A: 
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

Edit: 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.

Mike
Oops. I really should try the code I write before posting it. Of course you are correct, the ForEach<> loop will not work whereas the Enumerable.Repeat does work very nicely. It doesn't answer my question about the performance issue, but is definitely good info...
DaveN59
On second thought, it does answer the question -- you explained how the 2 approaches compare to each other, and provided another alternative. You get the points for this one...
DaveN59
+1  A: 

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.

Digicoder
A: 

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.

Morten Mertner
+1  A: 

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.

Lucero