加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

VB.NET vs. C#, round 2: Pounding on performance--VB.NET vs C

发布时间:2020-12-17 00:13:16 所属栏目:大数据 来源:网络整理
导读:VB.NET vs C#,第二波:效率碰撞 从效率的观点看,所有的.NET性能都一样吗?答案可能会让你大吃一惊。看看我们在深一层次研究代码时发现了什么。 如果说所有新技术在幼年成长中共享一个属性的话,那就是一大堆问题。微软的新.NET开发框架也是一样。 因此,我

VB.NET vs C#,第二波:效率碰撞

从效率的观点看,所有的.NET性能都一样吗?答案可能会让你大吃一惊。看看我们在深一层次研究代码时发现了什么。
如果说所有新技术在幼年成长中共享一个属性的话,那就是一大堆问题。微软的新.NET开发框架也是一样。
因此,我们决定在这里建一个区,专门回答关于.NET开发的问题。所以如果你对于微软新的开发平台有疑问的话,尽管将问题发过来,我尽力解决它。
我们接到一个关于性能的问题,是来自Vladimir Srecovic的问题。

C#性能标杆

Q:我看到过报道C#产生IL(中间语言)代码,比VB.NET产生的代码运行速度快,是真的吗?
A:我对这个问题的回答是否定的,我从来没有看到任何证据表明C#在速度上具有优势,并且认为存在任何重要的性能不同是不可能的。毕竟IL代码被相同的JIT编译器编译成自然代码,忽略是哪一个IL编译器生成的。所以至少在理论上,只要你的IL编译器符合标准,相等的VB.NET,C#或者甚至是COBOL.NET代码都将编译为基本相同的IL代码。
无论如何,这些都是传统的想法。为了更加彻底地证明,我决定用一个小实验看看这是否合理。我选择了TypeFinder样本应用程序的VB.NET和C#版本(在Program FilesMicrosoft.NetFrameworkSDKSamplesapplicationstypefinder中查看)并编译它们。下一步,我选取结果执行文件,并通过MSIL disassembler utility(Program FilesMicrosoft.NetFrameworkSDKBinildasm.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的专家,当前记录也很少。但是从IL代码上看,尽管两片代码功能相同并且以相同顺序执行相同任务,但是最后的IL代码却非常不同。这似乎能很明显地看出来。
  • 5个VB.NET编译器生成的指令代码时nop,根据微软当前文档,意思是“没有操作”或者“通过”。
  • VB.NET IL在.locals部分声明了一个额外的局部变量,类型为int32。C# IL中则直接指向这个类。
  • VB.NET IL使用6个指令创建StringBuilder对象,而C#只用了5个。VB.NET指令中一个是nop。
  • 两个for循环都用了13个指令。有趣的是,VB.NET的for循环中一个指令是nop。
有谁愿意回答以下吗?
我希望有IL的大牛能够更加深入地解释一下这里是怎么回事。
一些奇怪的事情确实不对劲。尽管这里没有确切的证据,但是确实VB.NET编译器生成代码要比对手C#稍微低效一些。这似乎支持了这个结论,至少在本例子中,C#确实比同样的VB.NET代码更加出色。因为我们正使用测试版,所以这些都可能改观。所以,我们静候进一步消息。所以可能还有下一章节继续这个问题的讨论。
原文链接:http://www.techrepublic.com/article/vbnet-vs-c-round-2-pounding-on-performance/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读