Background
Today, after conducting control tests, my colleagues and I discovered some strange things related to the performance of C # code and VB.NET code.
We started comparing C # and Delphi Prism, calculating prime numbers, and found that Prism was about 30% faster. I realized that CodeGear optimized the code when generating IL ( exe was about twice as large as C # and had all kinds of different ILs in it).
I decided to write a test in VB.NET, believing that Microsoft compilers would eventually write essentially the same IL for each language. However, the result was more shocking: the code worked more than three times slower in C # than VB with the same operation!
The generated IL was different, but not very so, and I'm not good enough to read it to understand the differences.
Benchmarks
I have 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 specifications and notes
- Intel Core 2 Quad 6600 @ 2.4Ghz
Each machine I tested on has a noticeable difference in test results between C # and VB.NET.
Both console applications were compiled in Release mode, but otherwise the project settings were not changed from the default values created 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 the execution of C # Math.Sqrt() slower than VB.NET?
Matt Winckler Jun 11 '10 at 20:22 2010-06-11 20:22
source share