So I saw this sort of code inside a loop (doing inversion of data) in C# the other day; assume x is a double:
dblValue = dblValue * -1.0d;
I wondered what the speed comparison was compared to this:
dblValue = -dblValue;
I expected the second to be faster. I decided to find out. After testing floating point numbers, I also decided to try the same thing with integers just to see. Here is my code set.
#define FP_MULT //#define FP_NEG //#define INT_MULT //#define INT_NEG using System; using System.Diagnostics; class Script { [STAThread] static public void Main(string[] args) { #if FP_MULT || FP_NEG double poo = 0d; #endif #if INT_MULT || INT_NEG int poo = 0; #endif Stopwatch stopWatch = new Stopwatch(); for (int idx = 0; idx < 1000000000; idx++) { stopWatch.Start(); #if FP_MULT poo = -1.0d * poo; #endif #if FP_NEG || INT_NEG poo = -poo; #endif #if INT_MULT poo = -1 * poo; #endif stopWatch.Stop(); } TimeSpan ts = stopWatch.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}.{2:00}", ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine(elapsedTime); } }
The program was compiled using .NET 4.0 64 bit framework. The exe was compiled to ILOnly verified using CorFlags.exe. This means the exe was running in 64 bit mode.
The test machine is a Dell Precision M4800. The process is an Intel Core i7-4800MQ CPU at 2.70 GHz with 16GB ram. The OS is Windows 7 Professional 64 bit with SP1.
Here is the results. I didn’t really average anything but everytime I ran every one of these tests, the values were always similar. I have also included the IL for the operation under test. (I used ILSpy.)
define | time | IL |
---|---|---|
FP_MULT | 15.49s | ldc.r8 -1; ldloc.0; mul; stloc.0 |
FP_NEG | 15.35s | ldloc.0; neg; stloc.0 |
INT_MULT | 15.35s | ldc.i4.m1; ldloc.0; mul; stloc.0 |
INT_NEG | 15.43s | ldloc.0; neg; stloc.0 |
It has been awhile since I have evaluated floating point and integer math but am impressed that the timing is very similar.
I think I may try this on the same machine using a simple C++ program and performance counters to see the results and dive deeper into this.
Follow up note: I now don’t believe I accurate measured anything as the stopwatch opcodes were likely more plentiful then the code under test. However, it was an interesting experiment and we learned about the stopwatch in .NET.