Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Array.Copy() faster than for loop, for 2D arrays?

Tags:

performance

c#

I recently changed

        this.FieldValues = new object[2, fieldValues.GetUpperBound(1) + 1];
        for (int i = 0; i < FieldCount; i++)            
        {
            this.FieldValues[Current, i] = fieldValues[Current, i];
            this.FieldValues[Original, i] = fieldValues[Original, i];
        }

to

        FieldValues = new object[2, fieldValues.GetLength(1)];
        Array.Copy(fieldValues, FieldValues, FieldValues.Length); 

Where the values of Current and Original are constants 0 and 1 respectively. FieldValues is a field and fieldValues is a parameter.

In the place I was using it, I found the Array.Copy() version to be faster. But another developer says he timed the for-loop against Array.Copy() in a standalone program and found the for-loop faster.

Is it possible that Array.Copy() is not really faster? I thought it was supposed to be super-optimised!

like image 961
PeteAC Avatar asked Sep 20 '11 10:09

PeteAC


2 Answers

In my own experience, I've found that I can't trust my intuition about anything when it comes to performance. Consequently, I keep a quick-and-dirty benchmarking app around (that I call "StupidPerformanceTricks"), which I use to test these scenarios. This is invaluable, as I've made all sorts of surprising and counter-intuitive discoveries about performance tricks. It's also important to remember to run your benchmark app in release mode, without a debugger attached, as you otherwise don't get JIT optimizations, and those optimizations can make a significant difference: technique A might be slower than technique B in debug mode, but significantly faster in release mode, with optimized code.

That said, in general, my own testing experience indicates that if your array is < ~32 elements, you'll get better performance by rolling your own copy loop - presumably because you don't have the method call overhead, which can be significant. However, if the loop is larger than ~32 elements, you'll get better performance by using Array.Copy(). (If you're copying ints or floats or similar sorts of things, you might also want to investigate Buffer.BlockCopy(), which is ~10% faster than Array.Copy() for small arrays.)

But all that said, the real answer is, "Write your own tests that match these precise alternatives as closely as possible, wrap them each with a loop, give the loop enough iterations for it to chew up at least 2-3 seconds worth of CPU, and then compare the alternatives yourself."

like image 124
Ken Smith Avatar answered Oct 02 '22 23:10

Ken Smith


The way .Net works under the hood, I'd guess that in an optimized situation, Array.Copy would avoid bounds checking.

If you do a loop on any type of collection, by default the CLR will check to make sure you're not passing the end of the collection, and then the JIT will either have to do a runtime assessment or emit code that doesn't need checking. (check the article in my comment for better details of this)

You can modify this behaviour, but generally you don't save that much. Unless you're in a tightly executed inner loop where every millisecond counts, that is.

If the Array is large, I'd use Array.Copy, if it's small, either should perform the same.

I do think it's bounds checking that's creating the different results for you though.

like image 38
Russ Clarke Avatar answered Oct 03 '22 01:10

Russ Clarke