In jedem Fachgebiet gibt es Fragestellungen, die von den in die Materie involvierten Personen sofort richtig beantwortet werden. Das Gebiet der Softwareentwicklung bildet da natürlich keine Ausnahme. Ich glaube, jedem Entwickler dürfte klar sein, dass zwischen VBA und C# (beide aus dem Hause Microsoft stammend) Welten liegen. Deswegen geht es in diesem Beitrag nicht um die Frage „Ist C# schneller als VBA?“, sondern vielmehr „Um welchen Faktor ist C# schneller als VBA?“
Vergleichsdurchführung
Um einen Vergleich anzustellen, habe ich in beiden Sprachen ein einfaches Programm mit identischem Aufbau entwickelt, welches eine bestimmte Anzahl von Primzahlen ermittelt. Bei der Programmentwicklung ging es dabei nicht darum, ein möglichst effizientes Algorithmus (denn das ist es definitiv nicht) für die Primzahlenermittlung zu entwickeln, sondern darum, den Rechner einfach eine Weile beschäftigen zu können. Die Generierung von 20.000 Primzahlen sollte dafür mehr als ausreichend sein.
Ergebnis
Bei dem Laufzeitvergleich der beiden Programme ging es nicht wirklich um Millisekunden, sodass ich ganz unkonventionell einfach mit meinem Handy die Zeit stoppte. Ich hoffe nur, dass der Test durch die währenddessen auf dem Rechner abgespielte Musik nicht verfälscht wurde 🙂
Fazit
Laufzeit C#-Programm: 5 Sekunden
Laufzeit VBA-Programm: 24 Sekunden
Wie es auch zu erwarten war, ist das Ergebnis mehr als eindeutig. Um ehrlich zu sein, hat mich aber fast der 5 fache Performanceabstand dennoch überrascht. Aber letztendlich gleicht die Softwareentwicklung in vielerlei Hinsicht dem Handwerk, wo für jeden Einsatzzweck unterschiedliche Werkzeuge gibt. Rein theoretisch kann man auch mit einer Bohrmaschine Nägel in die Wand reinhämmern. Zum Bohren kann diese aber dennoch viel sinnvoller eingesetzt werden :-).
So ist es auch mit VBA, womit sich echt gut kaufmännische Prozesse automatisieren und Anwendungen für mittlere Datenmengen realisieren lassen. Für hoch performante Anwendungen, die Millionen von Einzeloperationen ausführen, wie zum Beispiel der oben durchgeführte Vergleich mit den Primzahlen, gibt es geeignetere Programmiersprachen.
Anschließend habe ich noch aus Interesse noch einen weiteren Performancevergleich durchgeführt, nämlich mit PowerShell. Mit dieser Scriptsprache hatte ich bisher kaum Berührungspunkte. Das damit entwickelte Programm am langsamsten und hat mit rund 250 Sekunden rund 50zig fache des C#- und rund 10fache des-VBA-Programms benötigt. Auch bei dieser Sprache gilt, dass sie nicht unbedingt für hoch performante Operationen geeignet ist.
VBA-Quellcode
Private Sub startTest()
Dim lngPrimeNumbers() As Long
Dim varPrimeNumber As Variant
lngPrimeNumbers = getPrimeNumbers(20000)
Debug.Print "done"
End Sub
Private Function getPrimeNumbers(numberOfPrimeNumbers) As Long()
Dim lngPrimeNumbers() As Long
Dim lngPrimeNumberIndex As Long
Dim lngPrimeCandidate As Long
ReDim lngPrimeNumbers(1 To numberOfPrimeNumbers) As Long
lngPrimeNumberIndex = 1
lngPrimeCandidate = 2
Do While (numberOfPrimeNumbers >= lngPrimeNumberIndex)
If isPrimeNumber(lngPrimeCandidate) Then
lngPrimeNumbers(lngPrimeNumberIndex) = lngPrimeCandidate
lngPrimeNumberIndex = lngPrimeNumberIndex + 1
End If
lngPrimeCandidate = lngPrimeCandidate + 1
Loop
getPrimeNumbers = lngPrimeNumbers
End Function
Private Function isPrimeNumber(primeNumber As Long) As Boolean
Dim lngIndex As Long
Dim bolPrimeNumber As Boolean
bolPrimeNumber = True
For lngIndex = 2 To primeNumber - 1
If primeNumber Mod lngIndex = 0 Then
bolPrimeNumber = False
Exit For
End If
Next lngIndex
isPrimeNumber = bolPrimeNumber
End Function
C#-Quellcode
using System;
namespace Primzahlen
{
internal class Program
{
static void Main(string[] args)
{
int[] primes = PrimzahlGenerator.GetPrimNumbers(20000);
StringBuilder t = new StringBuilder();
Console.WriteLine("Done");
Console.ReadKey();
}
}
internal static class PrimzahlGenerator
{
internal static int[] GetPrimNumbers(int numberOfPrimeNumbers)
{
int[] primeNumbers = new int[numberOfPrimeNumbers];
int primeNumberIndex = 0;
int i = 2;
while(numberOfPrimeNumbers > primeNumberIndex)
{
if (IsPrimeNumber(i))
{
primeNumbers[primeNumberIndex] = i;
primeNumberIndex++;
}
i++;
}
return primeNumbers;
}
private static bool IsPrimeNumber(int primeNumber)
{
for (int i = 2; i < primeNumber; i++)
{
if (primeNumber % i == 0)
{
return false;
}
}
return true;
}
}
}