Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# execute Math.Sqrt() more slowly than VB.NET?

Background

While running benchmark tests this morning, my colleagues and I discovered some strange things concerning performance of C# code vs. VB.NET code.

We started out comparing C# vs. Delphi Prism calculating prime numbers, and found that Prism was about 30% faster. I figured CodeGear optimized code more when generating IL (the exe was about twice as big as C#'s and had all sorts of different IL in it.)

I decided to write a test in VB.NET as well, assuming that Microsoft's compilers would end up writing essentially the same IL for each language. However, the result there was more shocking: the code ran more than three times slower on C# than VB with the same operation!

The generated IL was different, but not extremely so, and I'm not good enough at reading it to understand the differences.

Benchmarks

I've included the code for each below. On my machine, VB finds 348513 primes in about 6.36 seconds. C# finds the same number of primes in 21.76 seconds.

Computer Specs and Notes

  • Intel Core 2 Quad 6600 @ 2.4Ghz

Every machine I've tested on there is a noticeable difference in the benchmark results between C# and VB.NET.

Both of the console applications were compiled in Release mode, but otherwise no project settings were changed from the defaults generated by Visual Studio 2008.

VB.NET code

Imports System.Diagnostics  Module Module1      Private temp As List(Of Int32)     Private sw As Stopwatch     Private totalSeconds As Double      Sub Main()         serialCalc()     End Sub      Private Sub serialCalc()         temp = New List(Of Int32)()         sw = Stopwatch.StartNew()         For i As Int32 = 2 To 5000000             testIfPrimeSerial(i)         Next         sw.Stop()         totalSeconds = sw.Elapsed.TotalSeconds         Console.WriteLine(String.Format("{0} seconds elapsed.", totalSeconds))         Console.WriteLine(String.Format("{0} primes found.", temp.Count))         Console.ReadKey()     End Sub      Private Sub testIfPrimeSerial(ByVal suspectPrime As Int32)         For i As Int32 = 2 To Math.Sqrt(suspectPrime)             If (suspectPrime Mod i = 0) Then                 Exit Sub             End If         Next         temp.Add(suspectPrime)     End Sub  End Module 

C# Code

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics;  namespace FindPrimesCSharp {     class Program {         List<Int32> temp = new List<Int32>();         Stopwatch sw;         double totalSeconds;           static void Main(string[] args) {              new Program().serialCalc();          }           private void serialCalc() {             temp = new List<Int32>();             sw = Stopwatch.StartNew();             for (Int32 i = 2; i <= 5000000; i++) {                 testIfPrimeSerial(i);             }             sw.Stop();             totalSeconds = sw.Elapsed.TotalSeconds;             Console.WriteLine(string.Format("{0} seconds elapsed.", totalSeconds));             Console.WriteLine(string.Format("{0} primes found.", temp.Count));             Console.ReadKey();         }          private void testIfPrimeSerial(Int32 suspectPrime) {             for (Int32 i = 2; i <= Math.Sqrt(suspectPrime); i++) {                 if (suspectPrime % i == 0)                     return;             }             temp.Add(suspectPrime);         }      } } 

Why is C#'s execution of Math.Sqrt() slower than VB.NET?

like image 665
Matt Winckler Avatar asked Jun 11 '10 20:06

Matt Winckler


People also ask

Why does letter C exist?

Like the letter G, C emerged from the Phoenician letter gimel (centuries later, gimel became the third letter of the Hebrew alphabet). In ancient Rome, as the Latin alphabet was being adapted from the Greek and Etruscan alphabets, G and C became disambiguated by adding a bar to the bottom end of the C.

Does the letter C need to exist?

This is a very important rule considering about 25% of words in our language contain a C.] So why do we need a C? When we combine the C with an H we DO make a unique sound. Without a C we would go to Hurch instead of Church, we would listen to a Hime instead of a Chime, etc.

Is the letter C useless?

But yeah, here are all the letters from most useless to most useful: X, C, Q, Y, W, H, Z, V, B, D, G, P, E, M, L, U, J, R, F, N, K, A, I, T, S, O. I hope you enjoyed this.

Why is C named so?

Quote from wikipedia: "A successor to the programming language B, C was originally developed at Bell Labs by Dennis Ritchie between 1972 and 1973 to construct utilities running on Unix." The creators want that everyone "see" his language. So he named it "C".


2 Answers

The C# implementation is recalculating Math.Sqrt(suspectPrime) each time through the loop, while VB only calculates it at the beginning of the loop. This is just due to the nature of the control structure. In C#, for is just a fancy while loop, while in VB it's a separate construct.

Using this loop will even up the score:

        Int32 sqrt = (int)Math.Sqrt(suspectPrime)         for (Int32 i = 2; i <= sqrt; i++) {              if (suspectPrime % i == 0)                  return;          } 
like image 109
Gabe Avatar answered Oct 05 '22 21:10

Gabe


I agree with the statement that the C# code is computing sqrt on every iteration and here is the proof straight out of Reflector:

VB version:

private static void testIfPrimeSerial(int suspectPrime) {     int VB$t_i4$L0 = (int) Math.Round(Math.Sqrt((double) suspectPrime));     for (int i = 2; i <= VB$t_i4$L0; i++)     {         if ((suspectPrime % i) == 0)         {             return;         }     }     temp.Add(suspectPrime); } 

C# version:

 private void testIfPrimeSerial(int suspectPrime) {     for (int i = 2; i <= Math.Sqrt((double) suspectPrime); i++)     {         if ((suspectPrime % i) == 0)         {             return;         }     }     this.temp.Add(suspectPrime); } 

Which kinda points to VB generating code that performs better even if the developer is naive enough to have the call to sqrt in the loop definition.

like image 27
Otávio Décio Avatar answered Oct 05 '22 21:10

Otávio Décio