RAW PERFORMANCE: VB6.0 VS. VB.NET AND C#
By Brad Gile
(
http://www.vb
-
faq.com/Articles/Gile/raw_performance.asp
)
Microsoft introduced the .NET framework and language specifications
for it that seemed
to place high emphasis on (1) web services and applications or (2) database applications
on the desktop. This, of course, is quite natural because almost all apps fall into one of
these categories. There are, however, VB programmers who
write good old fashioned
extreme number crunching mathematical apps, who might reasonably ask, “OK, so
VB.NET (or C#) is great. Will I lose performance with pure mathematical apps if I move
from VB 6 to VB.NET or C#?”
This question was my primary concer
n, so I decided to test it after the
final release of Visual Studio.NET. I have been programming in Visual
Basic since version 1.0 and various DOS versions of BASIC since the
early 1980s, so I have a very strong interest in the question whether
VB.NET (or
C#) traded mathematical performance for other features.
The answer, in short, is a resounding “NO!”. Just the opposite! Here
are the basic results of my testing:
1.
Run times may be cut by 50% or more using VB.NET or C#.
2.
It doesn’t matter which language y
ou use. C# and VB.NET
generate essentially the same performance.
In my testing, I wanted to use code that would be useful in a real application. So, I
decided to use the most important probability distribution in mathematics: the Standard
Normal Distrib
ution and its Inverse. These functions are central to statistical analyses and
Monte Carlo simulations. It was, of course, helpful that I already had VB 6 code for
these.
The test itself is quite simple. From a command button, generate 100,000 numbers th
at
are normally distributed with mean zero and variance 1. This is done by selecting
100,000 values between zero and 1 and calculating the Standard Normal Inverse of each
one. I selected 100,000 as a number that would be large enough that would take at le
ast a
couple seconds to loop through with my 2.0 Ghz Pentium 4. The time taken to do this is
displayed in a text box.
The Results on my PC: Execution times of 3.475 seconds in VB 6, 1.162 seconds in
VB.NET and the 1.232 seconds in C#
! Both .NET versions
were compiled in release
mode, and the VB 6 code was compiled with all error checking removed!
This result is nothing less than astonishing! We get a 65% reduction in
run time, and the difference between VB.NET and C# is negligible!
Now this is not to say
that there are no differences between VB.NET
and C#; there undoubtedly are, but Microsoft has stated that
performance differences between the two should be minimal. This is
the case here.
But the differences between VB6 and VB.NET/C# with respect to pu
re
performance are HUGE! This is undoubtedly due to both (1) new
compilers and (2) the new and massive .NET framework for which they
are designed.
The code in each of the three languages is shown below. The code
itself is quite straightforward, but I do
have a few comments on it.
VB.NET does allow you to use legacy VB6 code using Option Explicit
instead of Option Strict AND has a whole namespace for backward
compatibility with VB6. In my analysis here (and in ALL VB.NET code I
write), I use Option Strict
everywhere and I do not invoke the special
namespace for legacy code. I do this because it seems logical and
likely that constructs designed to support legacy VB 6 code will either
not work sometime in the future or cause hard to find bugs. Moreover,
for
new code, such crutches are totally unnecessary.
C# has no options because it is, by default, a strongly typed language.
C# also has no exponentiation operator and must use the Math.pow
function. Accordingly, I did the VB.NET code using both the usual ^
operator and, alternatively, Math.pow as shown here. There is no
difference in performance between the two.
THE CODE:
1.
VB 6.0
Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As
Long
Private Sub Command1_Click()
Dim BeginTime
As Long, EndTime As Long
Dim J As Long
Dim X As Double, Y As Double
Dim z As Double
'Create 100,000 Normally Distributed numbers with
'Mean 0 and Standard Deviation 1.
'VB 6.0 Version..................................
'THIS WILL BE DONE IN VB.NET AND C# F
OR COMPARISON!
BeginTime = GetTickCount()
For J = 1 To 100000
X = 0.00001 * (J
-
0.5)
Y = StandardNormalInverse(X)
Next J
EndTime = GetTickCount()
z = 0.001 * (EndTime
-
BeginTime)
Text1.Text = "Run time = " & CStr(z) & " seconds."
End Sub
Option Exp
licit
Public Const Pi As Double = 3.14159265358979
Private Function Density(ByVal X As Double) As Double
Density = 1 / (2 * Pi) ^ 0.5 * Exp(
-
0.5 * X ^ 2)
End Function
Public Function StandardNormal(ByVal X As Double) As Double
Dim a(4) As Double, K As
Double
Dim L As Double
Dim q As Double
Dim nx As Double
Dim SND As Double
Dim J As Integer
Dim S As Double
a(0) = 0.31938153
a(1) =
-
0.356563782
a(2) = 1.781477937
a(3) =
-
1.821255978
a(4) = 1.330274429
K = 0.2316419
L = Abs(X)
q = 1 / (1 + K * L)
nx = D
ensity(L)
'nx == f(abs(x))
For J = 0 To 4
S = S + a(J) * q ^ (J + 1)
Next J
SND = 1
-
nx * S
'SND = PHI(abs(x))
If (X < 0) Then
SND = 1
-
SND
End If
'NOW SND = PHI(x)
StandardNormal = SND
End Function
Public Function StandardNormalInverse(B
yVal R As Double) As
Double
Dim Delta As Double
Dim X As Double, Y As Double
X = 0
Delta = 1
Do Until Delta <= 0.000000001
Y = X
-
(StandardNormal(X)
-
R) / Density(X)
Delta = Abs(Y
-
X)
X = Y
Loop
StandardNormalInverse = Y
End Function
**************END VB 6.0 CODE******************
2.
VB.NET
Option Strict On
Private Sub But
ton1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim BeginTime As Long, EndTime As Long
Dim J As Long
Dim X As Double, Y As Double
Dim z As Double
'Create 100,000 Normally
Distributed numbers with
'Mean 0 and Standard Deviation 1.
'VB.NET Version..................................
BeginTime = System.Environment.TickCount()
For J = 1 To 100000
X = 0.00001 * (J
-
0.5)
Y =
NormalFunctions.StandardNormalInverse(X)
Next J
EndTime = System.Environment.TickCount()
z = 0.001 * (EndTime
-
BeginTime)
TextBox1.Text = "Run time = " & CStr(z) & "
seconds."
End Sub
Public Class NormalFunctions
Private Shared Function Density(ByVal X As Double) As
Double
Dim Y As Double
Y = Math.Pow(2 * Math.PI,
-
0.5) * Math.Exp(
-
0.5 * X
* X)
Return Y
End Function
Public Shared Function StandardNormal(ByVal X As
Double) As Double
Dim a(4) As Double, K As Double
Dim L As Double
Dim q As Double
Dim nx As Double
Dim SND As Double
Dim J As Integer
Dim S As Double
a(0) = 0.31938153
a(1) =
-
0.356563782
a(2)
= 1.781477937
a(3) =
-
1.821255978
a(4) = 1.330274429
K = 0.2316419
L = Math.Abs(X)
q = 1 / (1 + K * L)
nx = Density(L)
'nx == f(abs(x))
For J = 0 To 4
S = S + a(J) * q ^ (J + 1)
Next J
SND = 1
-
nx * S
'SND = PHI(abs(x))
If (X < 0) Then
SND = 1
-
SND
End If
'NOW SND = PHI(x)
Return SND
End Function
Public Shared Function StandardNormalInverse(By
Val R As
Double) As Double
Dim Delta As Double
Dim X As Double, Y As Double
X = 0
Delta = 1
Do Until Delta <= 0.000000001
Y = X
-
(StandardNormal(X)
-
R) / Density(X)
Delta = Math.Abs(Y
-
X)
X = Y
Loop
Return Y
End Function
End Class
*****************END VB.NET CODE***************
3.
C#:
private void button1_Click(object sender, System.EventArgs
e)
{
int BeginTicks=System.Environment.TickCount;
for(int j=1
;j<100001;j++)
{
double x=.00001*(j
-
.5);
double
y=NormalFunctions.StandardNormalInverse (x);
}
int EndTicks=System.Environment.TickCount;
double Elapsed=.001*(EndTicks
-
BeginTicks);
textBox1.Text ="Run Time = " +
Elapsed.ToStri
ng ();
using System;
namespace CsharpNormal
{
/// <summary>
/// Summary description for NormalFunctions.
/// </summary>
public class NormalFunctions
{
//Define density function as private static
private static double Density(double x)
{do
uble y=Math.Pow (2*Math.PI ,
-
.5)*Math.Exp(
-
.5*x*x);
return y;
}
//Define cumulative distribution as public static
public static double StandardNormal(double x)
{
double [] a=new double[5];
a[0]=.31938153;
a[1]=
-
.356563782;
a[2]=1.7814
77937;
a[3]=
-
1.821255978;
a[4]=1.330274429;
double K=.2316419;
double L=Math.Abs(x);
double nx=Density(L);
double q=1/(1+K*L);
double S=0;
for(int j=0;j<5;j++)
{
S+= a[j]*Math.Pow(q,j+1);
}
double SND=1
-
nx*S;
if(x<
0)
{
SND=1
-
SND;
}
return SND;
}
public static double StandardNormalInverse(double R)
{
double Delta=1;
double X=0;
double Y=0;
do
{
Y=X
-
(StandardNormal(X)
-
R)/Density(X);
Delta=Math.Abs (Y
-
X);
X=
Y;
}
while (Delta>.000000001);
return Y;
}
public NormalFunctions()
{
//
// TODO: Add constructor logic here
//
}
}
}
***************END C# CODE********************
Enter the password to open this PDF file:
File name:
-
File size:
-
Title:
-
Author:
-
Subject:
-
Keywords:
-
Creation Date:
-
Modification Date:
-
Creator:
-
PDF Producer:
-
PDF Version:
-
Page Count:
-
Preparing document for printing…
0%
Comments 0
Log in to post a comment