views:

234

answers:

3

Are methods calls really so slow or is there something wrong in my computer?

static void Main(string[] args) {
    Stopwatch sw = new Stopwatch(); sw.Start(); 
    for (int i = 0; i < 10000000; i++) {
        double z = Math.Pow(i,2);
    }
    Console.WriteLine(sw.ElapsedMilliseconds);
    sw = Stopwatch.StartNew();
    for (int i = 0; i < 10000000; i++) {
        Noop();
    }
    Console.WriteLine(sw.ElapsedMilliseconds);
}

static void Noop() { }

The first loop takes 1600 - 1700 milliseconds, while the second loop takes 3100 - 3200 milliseconds in my system (Celeron D 2.53 Ghz 512 MB RAM Windows XP SP3 .NET 3.5). It's a commandline project. I got similar results with VB.Net .

EDIT: I think I found the answer.

+5  A: 

Chances are you either:

  • Built in debug mode
  • Ran in the debugger.

My results:

c:\Users\Jon\Test>csc /o+ /debug- Test.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.


c:\Users\Jon\Test>test
1723
13

Is that more like what you'd expect? Even with /debug+ /o- I get much better results than your original ones when running from the command line, which suggests you were running in the debugger. Not a good idea for performance tests :)

Jon Skeet
Jon, even in debug mode I get a result very similar to yours.
Konrad Rudolph
Running in the debugger, or just building in debug mode?
Jon Skeet
Can't believe you are using Vista
Greg Dean
@Greg - Could be Server 2008 (my preferred desktop OS), or windows 7.
Mark Brackett
Nope, it's Vista. I know it's not "cool" to say so, but I actually rather like Vista.
Jon Skeet
+1  A: 

Whatever the reason, this has nothing to do with method calls. For one thing, such method calls are efficient. For another, your first example also calls a method. Thirdly, the second method call will be inlined and since nothing happens there, the second loop will actually be completely empty. The compiler could even optimize away the entire loop.

Finally, I can't reproduce your result, neither in debug nor in release mode.

Konrad Rudolph
+4  A: 

1723 13 Is that more like what you'd expect?

Yes, that's what I would expect. I'm not running in debug mode (debug mode gives me 1900/3200). Running it with the IDE open or closed I get the same results. Using csc or using ngen install does not change the result. I think I should reinstall .net framework.

EDIT:

Thanks for the answers.
Reinstalling the framework did not fix the problem. After testing with a virtual machine I got results that made sense. I finally found the problem:
Some time ago I installed a profiler called ProfileSharp. I don't know what (or why) the profiler was doing without my authorization while it was Closed, but since the moment I uninstalled it I'm getting 6 ms for the second loop. I still need to reinstall it and do some tests to see if it that was the culprit.

EDIT 2:

The profiler has a option to "Automatically attach and start profiling new processes" that it's enabled by default. When the profiler closes it's supposed to stop the profiling and indeed does in my tests with the virtual machine, but for some reason once it didn't and started profiling every .net process in the background (System, ASP and Microsoft namespaces are excluded by default so it didn't affect Math.Pow too much).

ggf31416
Don't bother reinstalling the framework!
Greg Dean
Thanks for the follow-up information. Good to know.
Konrad Rudolph
Wow. That's a pretty intrusive profiler...
Jon Skeet