Reputation: 9
I have the same project written with Vb.net and C # prepared with Visual Studio 2015 below. Visual Basic project:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim j As Int32 = 0
'
Dim Offset As Double = 0D ' Offset
Dim Gain As Double = 1D ' Gain
Dim Freq As Double = 1D ' Frequency
Dim M As Int32 = 3000 ' Number of Block
Dim N As Int32 = 30000 ' Number of data each block
Dim delta As Double = 0 ' Sample rate
Dim DataCount As Int32 = N * M ' Total data count
'
Dim X As Double
Dim Y As Double
'
delta = N / DataCount
'
' Fonksiyon
'
Dim Time As Stopwatch
Time = New Stopwatch
Time.Start()
'
For b As Int32 = 0 To M - 1
For i As Int32 = 0 To N - 1
X = j * delta
Y = Offset + Gain * Math.Cos(X * Freq * Math.PI / 180.0)
j = j + 1
Next
Next b
'
Time.Stop()
Console.WriteLine("Elapsed time :{0}", Time.Elapsed)
End Sub
and C# project:
private void button1_Click(object sender, EventArgs e)
{
Int32 j = 0;
Double Offset = 0D; // Offset
Double Gain = 1D; // Gain
Double Freq = 1D; // Frequency
Int32 M = 3000; // Number of Block
Int32 N = 30000; // Number of data each block
Double delta = 0; // Sample rate
Int32 DataCount = N * M; // Total data count
//
Double X;
Double Y;
//
delta = N / DataCount;
//
// Fonksiyon
//
Stopwatch Time;
Time = new Stopwatch();
Time.Start();
//
for (Int32 b=0; b< M; b++) {
for (Int32 i= 0; i < N; i++) {
X = j * delta;
Y = Offset + Gain * Math.Cos(X * Freq * Math.PI / 180.0);
j = j + 1;
}
}
//
Time.Stop();
Console.WriteLine("Elapsed time :{0}", Time.Elapsed);
}
The projects were run three times and delay times were obtained.
Results obtained when the Visual Basic project is run;
Elapsed time :00:00:03.9066617
Elapsed time :00:00:03.9165436
Elapsed time :00:00:03.9031542
And the results obtained when the C # project is run;
Elapsed time :00:00:02.4870551
Elapsed time :00:00:02.4931171
Elapsed time :00:00:02.5005793
Different result in the same framework. There is more than a second difference between vb.net and C#.
Why is vb.net so slow?
Upvotes: 0
Views: 561
Reputation: 78185
The two codes have an important difference in this line:
delta = N / DataCount
In VB, this is arithmetical division. In C#, it is integer division.
In VB it returns 0.00033333...
, in C# it returns 0.
If you fix the VB code to also use integer division:
delta = N \ DataCount
the two codes begin to show exactly the same time.
Upvotes: 3
Reputation: 3693
Please check the generated IL code for C#
and VB.Net
. In my local machine, I observed that they are roughly equivalent but not the same. For example, In the case of VB.Net, it has extra checks for arithmetic addition, subtraction etc. VB.NET
uses opcodes such as sub.ovf
, mul.ovf
where as C# does not. I am providing the IL output for both cases. They are compile using release mode. You can see that they start to differ even from the number of local variables. VB has 13 locals where as C# 11 locals.
C#
.method /*06000002*/ private hidebysig instance void
button1_Click(
/*08000001*/ object sender,
/*08000002*/ class [mscorlib/*23000001*/]System.EventArgs/*01000014*/ e
) cil managed
{
.maxstack 2
.locals /*11000002*/ init (
[0] int32 j,
[1] float64 Offset,
[2] float64 Gain,
[3] float64 Freq,
[4] int32 M,
[5] int32 N,
[6] float64 delta,
[7] int32 DataCount,
[8] float64 X,
[9] class [System/*23000003*/]System.Diagnostics.Stopwatch/*01000015*/ Time,
[10] int32 b,
[11] int32 i
)
// [38 13 - 38 25]
IL_0000: ldc.i4.0
IL_0001: stloc.0 // j
// [40 13 - 40 32]
IL_0002: ldc.r8 0.0
IL_000b: stloc.1 // Offset
// [41 13 - 41 30]
IL_000c: ldc.r8 1
IL_0015: stloc.2 // Gain
// [42 13 - 42 30]
IL_0016: ldc.r8 1
IL_001f: stloc.3 // Freq
// [43 13 - 43 28]
IL_0020: ldc.i4 3000 // 0x00000bb8
IL_0025: stloc.s M
// [44 13 - 44 29]
IL_0027: ldc.i4 30000 // 0x00007530
IL_002c: stloc.s N
// [45 13 - 45 30]
IL_002e: ldc.r8 0.0
IL_0037: stloc.s delta
// [46 13 - 46 37]
IL_0039: ldloc.s N
IL_003b: ldloc.s M
IL_003d: mul
IL_003e: stloc.s DataCount
// [51 13 - 51 35]
IL_0040: ldloc.s N
IL_0042: ldloc.s DataCount
IL_0044: div
IL_0045: conv.r8
IL_0046: stloc.s delta
// [56 13 - 56 36]
IL_0048: newobj instance void [System/*23000003*/]System.Diagnostics.Stopwatch/*01000015*/::.ctor()/*0A00001D*/
IL_004d: stloc.s Time
// [57 13 - 57 26]
IL_004f: ldloc.s Time
IL_0051: callvirt instance void [System/*23000003*/]System.Diagnostics.Stopwatch/*01000015*/::Start()/*0A00001E*/
// [59 18 - 59 29]
IL_0056: ldc.i4.0
IL_0057: stloc.s b
IL_0059: br.s IL_009b
// start of loop, entry point: IL_009b
// [62 22 - 62 33]
IL_005b: ldc.i4.0
IL_005c: stloc.s i
IL_005e: br.s IL_008f
// start of loop, entry point: IL_008f
// [64 21 - 64 35]
IL_0060: ldloc.0 // j
IL_0061: conv.r8
IL_0062: ldloc.s delta
IL_0064: mul
IL_0065: stloc.s X
// [65 21 - 65 78]
IL_0067: ldloc.s X
IL_0069: ldloc.3 // Freq
IL_006a: mul
IL_006b: ldc.r8 3.14159265358979
IL_0074: mul
IL_0075: ldc.r8 180
IL_007e: div
IL_007f: call float64 [mscorlib/*23000001*/]System.Math/*01000024*/::Cos(float64)/*0A00001F*/
IL_0084: pop
// [66 21 - 66 31]
IL_0085: ldloc.0 // j
IL_0086: ldc.i4.1
IL_0087: add
IL_0088: stloc.0 // j
// [62 42 - 62 45]
IL_0089: ldloc.s i
IL_008b: ldc.i4.1
IL_008c: add
IL_008d: stloc.s i
// [62 35 - 62 40]
IL_008f: ldloc.s i
IL_0091: ldloc.s N
IL_0093: blt.s IL_0060
// end of loop
// [59 38 - 59 41]
IL_0095: ldloc.s b
IL_0097: ldc.i4.1
IL_0098: add
IL_0099: stloc.s b
// [59 31 - 59 36]
IL_009b: ldloc.s b
IL_009d: ldloc.s M
IL_009f: blt.s IL_005b
// end of loop
// [70 13 - 70 25]
IL_00a1: ldloc.s Time
IL_00a3: callvirt instance void [System/*23000003*/]System.Diagnostics.Stopwatch/*01000015*/::Stop()/*0A000020*/
// [71 13 - 71 66]
IL_00a8: ldstr "Elapsed time :{0}"
IL_00ad: ldloc.s Time
IL_00af: callvirt instance valuetype [mscorlib/*23000001*/]System.TimeSpan/*01000025*/ [System/*23000003*/]System.Diagnostics.Stopwatch/*01000015*/::get_Elapsed()/*0A000021*/
IL_00b4: box [mscorlib/*23000001*/]System.TimeSpan/*01000025*/
IL_00b9: call void [mscorlib/*23000001*/]System.Console/*01000026*/::WriteLine(string, object)/*0A000022*/
// [72 9 - 72 10]
IL_00be: ret
} // end of method Form1::button1_Click
VB.NET
.method /*06000014*/ private instance void
Button1_Click(
/*08000005*/ object sender,
/*08000006*/ class [mscorlib/*23000001*/]System.EventArgs/*01000027*/ e
) cil managed
{
.maxstack 2
.locals /*11000002*/ init (
[0] int32 j,
[1] float64 Offset,
[2] float64 Gain,
[3] float64 Freq,
[4] int32 M,
[5] int32 N,
[6] float64 delta,
[7] int32 DataCount,
[8] float64 X,
[9] class [System/*23000002*/]System.Diagnostics.Stopwatch/*0100002C*/ Time,
[10] int32 V_10,
[11] int32 b,
[12] int32 V_12,
[13] int32 i
)
// [3 13 - 3 27]
IL_0000: ldc.i4.0
IL_0001: stloc.0 // j
// [5 13 - 5 34]
IL_0002: ldc.r8 0.0
IL_000b: stloc.1 // Offset
// [6 13 - 6 32]
IL_000c: ldc.r8 1
IL_0015: stloc.2 // Gain
// [7 13 - 7 32]
IL_0016: ldc.r8 1
IL_001f: stloc.3 // Freq
// [8 13 - 8 30]
IL_0020: ldc.i4 3000 // 0x00000bb8
IL_0025: stloc.s M
// [9 13 - 9 31]
IL_0027: ldc.i4 30000 // 0x00007530
IL_002c: stloc.s N
// [10 13 - 10 32]
IL_002e: ldc.r8 0.0
IL_0037: stloc.s delta
// [11 13 - 11 39]
IL_0039: ldloc.s N
IL_003b: ldloc.s M
IL_003d: mul.ovf
IL_003e: stloc.s DataCount
// [17 9 - 17 30]
IL_0040: ldloc.s N
IL_0042: conv.r8
IL_0043: ldloc.s DataCount
IL_0045: conv.r8
IL_0046: div
IL_0047: stloc.s delta
// [22 9 - 22 29]
IL_0049: newobj instance void [System/*23000002*/]System.Diagnostics.Stopwatch/*0100002C*/::.ctor()/*0A000040*/
IL_004e: stloc.s Time
// [23 9 - 23 21]
IL_0050: ldloc.s Time
IL_0052: callvirt instance void [System/*23000002*/]System.Diagnostics.Stopwatch/*0100002C*/::Start()/*0A000041*/
// [25 9 - 25 36]
IL_0057: ldloc.s M
IL_0059: ldc.i4.1
IL_005a: sub.ovf
IL_005b: stloc.s V_10
IL_005d: ldc.i4.0
IL_005e: stloc.s b
IL_0060: br.s IL_00a8
// start of loop, entry point: IL_00a8
// [26 13 - 26 40]
IL_0062: ldloc.s N
IL_0064: ldc.i4.1
IL_0065: sub.ovf
IL_0066: stloc.s V_12
IL_0068: ldc.i4.0
IL_0069: stloc.s i
IL_006b: br.s IL_009c
// start of loop, entry point: IL_009c
// [27 17 - 27 30]
IL_006d: ldloc.0 // j
IL_006e: conv.r8
IL_006f: ldloc.s delta
IL_0071: mul
IL_0072: stloc.s X
// [28 17 - 28 73]
IL_0074: ldloc.s X
IL_0076: ldloc.3 // Freq
IL_0077: mul
IL_0078: ldc.r8 3.14159265358979
IL_0081: mul
IL_0082: ldc.r8 180
IL_008b: div
IL_008c: call float64 [mscorlib/*23000001*/]System.Math/*01000038*/::Cos(float64)/*0A000042*/
IL_0091: pop
// [29 17 - 29 26]
IL_0092: ldloc.0 // j
IL_0093: ldc.i4.1
IL_0094: add.ovf
IL_0095: stloc.0 // j
// [30 13 - 30 17]
IL_0096: ldloc.s i
IL_0098: ldc.i4.1
IL_0099: add.ovf
IL_009a: stloc.s i
IL_009c: ldloc.s i
IL_009e: ldloc.s V_12
IL_00a0: ble.s IL_006d
// end of loop
// [31 9 - 31 15]
IL_00a2: ldloc.s b
IL_00a4: ldc.i4.1
IL_00a5: add.ovf
IL_00a6: stloc.s b
IL_00a8: ldloc.s b
IL_00aa: ldloc.s V_10
IL_00ac: ble.s IL_0062
// end of loop
// [33 9 - 33 20]
IL_00ae: ldloc.s Time
IL_00b0: callvirt instance void [System/*23000002*/]System.Diagnostics.Stopwatch/*0100002C*/::Stop()/*0A000043*/
// [34 9 - 34 61]
IL_00b5: ldstr "Elapsed time :{0}"
IL_00ba: ldloc.s Time
IL_00bc: callvirt instance valuetype [mscorlib/*23000001*/]System.TimeSpan/*01000039*/ [System/*23000002*/]System.Diagnostics.Stopwatch/*0100002C*/::get_Elapsed()/*0A000044*/
IL_00c1: box [mscorlib/*23000001*/]System.TimeSpan/*01000039*/
IL_00c6: call void [mscorlib/*23000001*/]System.Console/*0100003A*/::WriteLine(string, object)/*0A000045*/
// [35 5 - 35 12]
IL_00cb: ret
} // end of method Form1::Button1_Click
Upvotes: 0