VB.NET vs C#,第二波:效率碰撞
如果说所有新技术在幼年成长中共享一个属性的话,那就是一大堆问题。微软的新.NET开发框架也是一样。
因此,我们决定在这里建一个区,专门回答关于.NET开发的问题。所以如果你对于微软新的开发平台有疑问的话,尽管将问题发过来,我尽力解决它。
我们接到一个关于性能的问题,是来自Vladimir Srecovic的问题。
C#性能标杆
A:我对这个问题的回答是否定的,我从来没有看到任何证据表明C#在速度上具有优势,并且认为存在任何重要的性能不同是不可能的。毕竟IL代码被相同的JIT编译器编译成自然代码,忽略是哪一个IL编译器生成的。所以至少在理论上,只要你的IL编译器符合标准,相等的VB.NET,C#或者甚至是COBOL.NET代码都将编译为基本相同的IL代码。
无论如何,这些都是传统的想法。为了更加彻底地证明,我决定用一个小实验看看这是否合理。我选择了TypeFinder样本应用程序的VB.NET和C#版本(在\Program Files\Microsoft.Net\FrameworkSDK\Samples\applications\typefinder中查看)并编译它们。下一步,我选取结果执行文件,并通过MSIL disassembler utility(\Program Files\Microsoft.Net\FrameworkSDK\Bin\ildasm.exe)查看两个编译器产生的IL。然后我比较这两片专门为相当简单的方法IndentedWriter.WriteLine产生的IL。你可以看到图A这个方法的VB.NET源,C#源在图B中。
图 A
VB.NET版本要比C#版本的稍微长一点。
图 B
C#版本用了7行代码。
当我比较最后的IL代码时,对我发现的事情大吃一惊:VB.NET版本比C#版本长9行(而且9KB)。你可以在列表A中看到VB.NET编译器产生的IL;C#编译器的结果出现在列表B中。
列表A:
.method public hidebysig instance void WriteLine(string message) cil managed { // Code size 75 (0x4b) .maxstack 3 .locals init ([0] int32 i,[1] class [mscorlib]System.Text.StringBuilder sb,[2] int32 _Vb_t_i4_0) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldfld bool NetSDKSamples.IndentedWriter::myPrintFlag IL_0007: brfalse.s IL_0048 IL_0009: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor() IL_000e: stloc.1 IL_000f: ldc.i4.0 IL_0010: ldarg.0 IL_0011: ldfld int32 NetSDKSamples.IndentedWriter::myIndent IL_0016: ldc.i4.1 IL_0017: sub.ovf IL_0018: stloc.2 IL_0019: stloc.0 IL_001a: br.s IL_002a IL_001c: ldloc.1 IL_001d: ldc.i4.s 32 IL_001f: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(char) IL_0024: pop IL_0025: nop IL_0026: ldloc.0 IL_0027: ldc.i4.1 IL_0028: add.ovf IL_0029: stloc.0 IL_002a: ldloc.0 IL_002b: ldloc.2 IL_002c: ble.s IL_001c IL_002e: ldloc.1 IL_002f: ldarg.1 IL_0030: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_0035: pop IL_0036: ldarg.0 IL_0037: ldfld class [mscorlib]System.IO.TextWriter NetSDKSamples.IndentedWriter::myTextWriter IL_003c: ldloc.1 IL_003d: callvirt instance string [mscorlib]System.Text.StringBuilder::ToString() IL_0042: callvirt instance void [mscorlib]System.IO.TextWriter::WriteLine(string) IL_0047: nop IL_0048: nop IL_0049: nop IL_004a: ret } // end of method IndentedWriter::WriteLine列表B:
.method public hidebysig instance void WriteLine(string message) cil managed { // Code size 66 (0x42) .maxstack 2 .locals ([0] class [mscorlib]System.Text.StringBuilder sb,[1] int32 i) IL_0000: ldarg.0 IL_0001: ldfld bool IndentedWriter::myPrintFlag IL_0006: brfalse.s IL_0041 IL_0008: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor() IL_000d: stloc.0 IL_000e: ldc.i4.0 IL_000f: stloc.1 IL_0010: br.s IL_001f IL_0012: ldloc.0 IL_0013: ldc.i4.s 32 IL_0015: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(char) IL_001a: pop IL_001b: ldloc.1 IL_001c: ldc.i4.1 IL_001d: add IL_001e: stloc.1 IL_001f: ldloc.1 IL_0020: ldarg.0 IL_0021: ldfld int32 IndentedWriter::myIndent IL_0026: blt.s IL_0012 IL_0028: ldloc.0 IL_0029: ldarg.1 IL_002a: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_002f: pop IL_0030: ldarg.0 IL_0031: ldfld class [mscorlib]System.IO.TextWriter IndentedWriter::myTextWriter IL_0036: ldloc.0 IL_0037: callvirt instance string [mscorlib]System.Text.StringBuilder::ToString() IL_003c: callvirt instance void [mscorlib]System.IO.TextWriter::WriteLine(string) IL_0041: ret } // end of method IndentedWriter::WriteLine编译代码后,我简单随便比较了以下,超过12次实验发现,C#版本的FindType.exe使用反射列出属于某一特定对象的方法,险胜于VB.NET版本。后者最快时间也比前者最慢时间要慢。
这到底是怎么回事?
有谁愿意回答以下吗?
我希望有IL的大牛能够更加深入地解释一下这里是怎么回事。
一些奇怪的事情确实不对劲。尽管这里没有确切的证据,但是确实VB.NET编译器生成代码要比对手C#稍微低效一些。这似乎支持了这个结论,至少在本例子中,C#确实比同样的VB.NET代码更加出色。因为我们正使用测试版,所以这些都可能改观。所以,我们静候进一步消息。所以可能还有下一章节继续这个问题的讨论。
原文链接:http://www.techrepublic.com/article/vbnet-vs-c-round-2-pounding-on-performance/