Arrière-plan
Lors de l'exécution de tests de référence, ce matin, mes collègues et j'ai découvert des choses étranges concernant l'exécution de code C# vs VB.NET code.
Nous avons commencé la comparaison de C# vs Delphi Prism calcul de nombres premiers, et a constaté que Prism est environ 30% plus rapide. J'ai pensé CodeGear code optimisé plus lors de la génération d'IL (l' exe
a été environ deux fois plus grand que C#'s et a eu toutes sortes de différents IL in.)
J'ai décidé d'écrire un test en VB.NET ainsi, en supposant que Microsoft compilateurs finirait par écrit essentiellement les mêmes IL pour chaque langue. Cependant, le résultat a été plus choquant: le code a couru plus de trois fois plus lent sur le C# que VB avec la même opération!
L'généré IL était différent, mais pas à l'extrême, et je ne suis pas assez bon à lire pour comprendre les différences.
Repères
J'ai inclus le code ci-dessous. Sur ma machine, VB trouve 348513 nombres premiers en sur 6.36 secondes. C# trouve le même nombre de nombres premiers dans 21.76 secondes.
Ordinateur Spécifications et des Notes
- Intel Core 2 Quad 6600 @ 2.4 Ghz
Chaque machine que j'ai testé il y a une différence notable dans les résultats de l'analyse comparative entre C# et VB.NET.
Les deux applications de console ont été compilé en mode Release, mais sinon aucun projet de paramètres ont été modifiés de la valeur par défaut généré par 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
Le Code C#
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);
}
}
}
Pourquoi le C#'exécution de Math.Sqrt()
plus lent que VB.NET?