1

As I am calling ummanaged dll from C#, I've gone through some testing about the performance of for-loop in C# and C...

The result amazed me in the way that as the loop goes over bigger range, the performance of C# decreases as compared to C..For smaller range,C# shown well performance over C....But, as upper range of for-loop increases, the C# performance degrades as compare to C....

Here is my testing code....

    [DllImport("Testing.dll", CallingConvention =  CallingConvention.Cdecl)]
    public static extern int SumLoop(int lowLimit, int highLimit);

    public static void Main(string[] args)
    {
        const int LowerRange = 1;
        const int HigherRange = 1000000;

        // Test with C# For Loop
        var watch1 = new Stopwatch();
        watch1.Start();
        int sum = 0;
        for (int i = LowerRange; i <= HigherRange; i++)
        {
            sum += i;
        }
        watch1.Stop();

        long elapseTime1 = watch1.ElapsedMilliseconds;

        // Test with C-for loop
        var watch2 = new Stopwatch();
        watch2.Start();
        int sumFromC = SumLoop(LowerRange , HigherRange);
        long elapseTime2 = watch2.ElapsedMilliseconds;
   }

Testing.dll:

__declspec(dllexport) int SumLoop(int lowLimit, int highLimit)
{
    int idx;
    int totalSum = 0;
    for(idx = lowLimit;idx<= highLimit; idx= idx +1)
    {
        totalSum += idx;
    }
    return totalSum;
}

Testing Result :

Testing 1 :

HigherRange : 1000000

C# Loop : 4 millisecond

C-loop : 9 millisecond

Testing 2 :

HigherRange : 10000000

C# Loop : 53 millisecond

C-loop : 36 millisecond

Testing 3 :

HigherRange : 100000000

C# Loop : 418 millisecond

C-loop : 343 millisecond

Here, I started above testing with the aim that C for-loop performance will be better than C# loop but it goes exactly opposite with my understanding and gone with this question and agreed...But when I increase the upper range of for loop, the C performance goes well as compared to C#...

Now,I'm thinking that is the appraoch of testing is wrong or is it the expected performance result?

Community
  • 1
  • 1
Akash KC
  • 16,057
  • 6
  • 39
  • 59

1 Answers1

3

What's happening here is that you are ignoring the fixed overhead of using P/Invoke to call the C function.

The C function will be faster than the C# version BUT because of the relatively large overhead of calling it, the C function will appear to be slower for small arrays because the calling overhead is a relatively large proportion of the overall time.

However, as you increase the size of the collection the overhead will become a smaller and smaller proportion of the overall time, until the extra speed of the C version asserts itself and you start to see it running faster.

If you look at the times for the C# function, you can see that it is indeed increasing more or less linearly with N, which you'd expect. Compare T = 4 with T = 418 after you increase N by a factor of 100. Just what you'd expect. But the C times do NOT appear to increase linearly, for the reason outlined above.

Incidentally, if you take at least two timings, you can use simultaneous equations to solve:

T = K + XN

Where K is the fixed overhead, and X is the overhead per element.

I have calculated from your timings that the fixed overhead for calling the unmanaged code is approximately 5.6 milliseconds and the overhead per element is 3.373737 x 10^-6 milliseconds.

That overhead seems somewhat large, but I guess there's some inaccuracies in the measured data.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • As I don't know much about P/Invoke, does it adds so much overhead that it appear as C is slower than C#..Shouldn't I use it or is there any alternative of P/Invoke? – Akash KC Feb 19 '13 at 09:35
  • There is no alternative I'm afraid (other than not calling unmanaged code). BUt what are your times like with a release build? – Matthew Watson Feb 19 '13 at 09:37
  • With the release build, I didn't notice much difference : for 10000000. it took 52ms(C#) and 40ms(C)....for 100000000, 418ms (C#) and 335ms(C).... – Akash KC Feb 19 '13 at 09:53
  • That sounds very unlikely and I think you are doing it wrong. How did you run it? If you run it by pressing F5 it will still do a debug run. I tried your code, and on my system with debug build, the c# loop takes 220ms and with release build it takes 64ms. The fact that your code doesn't seem to be printing the times leads me to suspect that you are running it under the debugger in order to inspect the variables. You need to add Console.WriteLine() to print the results, and run it OUTSIDE the debugger. – Matthew Watson Feb 19 '13 at 10:13