C# vb.net速度慢吗?
我用Vb.net和C#编写了相同的项目,并在下面用Visual Studio 2015编写。 Visual Basic项目:C# vb.net速度慢吗?,c#,vb.net,algorithm,C#,Vb.net,Algorithm,我用Vb.net和C#编写了相同的项目,并在下面用Visual Studio 2015编写。 Visual Basic项目: Private子按钮1\u单击(发送者作为对象,e作为事件参数)处理按钮1。单击 尺寸j为Int32=0 ' 双精度尺寸偏移=0D'偏移 双倍变暗增益=1D'增益 Dim Freq为双精度=1D'频率 尺寸M为Int32=3000'块数 尺寸N为Int32=每个数据块的30000'数据数量 双精度尺寸增量=0'采样率 Dim DATACUNT As Int32=N*M'总
Private子按钮1\u单击(发送者作为对象,e作为事件参数)处理按钮1。单击
尺寸j为Int32=0
'
双精度尺寸偏移=0D'偏移
双倍变暗增益=1D'增益
Dim Freq为双精度=1D'频率
尺寸M为Int32=3000'块数
尺寸N为Int32=每个数据块的30000'数据数量
双精度尺寸增量=0'采样率
Dim DATACUNT As Int32=N*M'总数据计数
'
将X调为双精度
双色
'
delta=N/数据计数
'
“方克西翁
'
像秒表一样暗的时间
时间=新秒表
开始时间()
'
对于b,Int32=0到M-1
对于i作为Int32=0到N-1
X=j*delta
Y=偏移量+增益*Math.Cos(X*Freq*Math.PI/180.0)
j=j+1
下一个
下一个b
'
时间,停止
WriteLine(“运行时间:{0}”,time.appeased)
端接头
和C#项目:
private void按钮1\u单击(对象发送者,事件参数e)
{
int32j=0;
双偏移量=0D;//偏移量
双增益=1D;//增益
双频=1D;//频率
Int32 M=3000;//块数
Int32 N=30000;//每个块的数据数
双增量=0;//采样率
Int32 DataCount=N*M;//总数据计数
//
双X;
双Y;
//
delta=N/数据计数;
//
//方克西翁
//
秒表时间;
时间=新秒表();
Time.Start();
//
对于(Int32 b=0;b
项目运行了三次,获得了延迟时间
运行Visual Basic项目时获得的结果
Elapsed time :00:00:03.9066617
Elapsed time :00:00:03.9165436
Elapsed time :00:00:03.9031542
Elapsed time :00:00:02.4870551
Elapsed time :00:00:02.4931171
Elapsed time :00:00:02.5005793
以及C#项目运行时获得的结果
Elapsed time :00:00:03.9066617
Elapsed time :00:00:03.9165436
Elapsed time :00:00:03.9031542
Elapsed time :00:00:02.4870551
Elapsed time :00:00:02.4931171
Elapsed time :00:00:02.5005793
不同的结果在同一个框架中。vb.net和C#之间的区别不止一秒
为什么vb.net这么慢?请检查生成的IL代码,查看
C
和vb.net
。在我的本地机器中,我观察到它们大致相同,但并不相同。例如,在VB.Net的情况下,它对算术加法、减法等有额外的检查。VB.Net
使用操作码,如sub.ovf
,mul.ovf
,而C不使用。我为这两种情况提供IL输出。它们是使用发布模式编译的。您可以看到,它们甚至开始与局部变量的数量不同。VB有13个局部变量,其中C#11个局部变量
C#
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
请检查生成的IL代码是否为
C
和VB.Net
。在我的本地机器中,我观察到它们大致相同,但并不相同。例如,在VB.Net的情况下,它对算术加法、减法等有额外的检查。VB.Net
使用操作码,如sub.ovf
,mul.ovf
,而C不使用。我为这两种情况提供IL输出。它们是使用发布模式编译的。您可以看到,它们甚至开始与局部变量的数量不同。VB有13个局部变量,其中C#11个局部变量
C#
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
这两种代码在这一行中有一个重要区别:
delta = N / DataCount
在VB中,这是算术除法。在C#中,它是整数除法。在VB中返回
0.00033333…
,在C中返回0
如果将VB代码修复为也使用整数除法:
delta = N \ DataCount
这两个代码开始显示完全相同的时间。这两个代码在这一行中有一个重要的区别:
delta = N / DataCount
在VB中,这是算术除法。在C#中,它是整数除法。在VB中返回
0.00033333…
,在C中返回0
如果将VB代码修复为也使用整数除法:
delta = N \ DataCount
这两个代码开始显示的时间完全相同。您在发行版中测试过这一点吗?您是否使用了值得尊敬的基准点工具?您是否尝试重置您的电脑并以相反的顺序运行这些程序。我的意思是先是C#one,然后是VB.NET。测量性能并不像在一个环路上启动两个秒表那么简单。顺便问一下,您是否在发布模式下设置了这两个代码?如果您想知道是否存在差异,请检查生成的IL中的两个代码段。顺便说一句,您只需要一行代码就可以创建和启动
秒表
,即Dim time=Stopwatch.StartNew()
。请尝试在vb项目的高级编译选项中启用未选中的算术。生成的IL使用执行溢出检查的.ovf
操作码。也可以将vb中的除法从/
切换到\
,后者执行整数除法,修改c,使其不是整数除法(将一侧转换为双精度),或者使用至少在整数/浮点除法中表现相同的值。在发布模式下编译,在VisualStudio外部运行,执行三个以上的测试(预热jit并删除一堆测试),并使用适当的基准框架谢谢您的评论。正如Pinkfloydx33所提到的,拆分过程存在问题。您是否在发行版中对此进行了测试,是否使用了值得尊敬的基准点工具?是否尝试重置您的电脑并以相反的顺序运行这些程序。我的意思是先是C#one,然后是VB.NET。测量性能并不像在一个环路上启动两个秒表那么简单。顺便问一下,您是否在发布模式下设置了这两个代码?如果您想知道是否存在差异,请检查生成的IL中的两个代码段。顺便说一下,您只需要一行代码就可以创建和启动秒表