【发布时间】:2010-09-22 09:01:36
【问题描述】:
类似于this 问题,但是对于 VB.NET,因为我了解到这是一个语言问题。
例如,编译器是否知道翻译
Dim s As String = "test" + "this" + “功能”
到
Dim s As String = "test this function"
从而避免字符串连接对性能的影响?
【问题讨论】:
标签: .net vb.net performance optimization
类似于this 问题,但是对于 VB.NET,因为我了解到这是一个语言问题。
例如,编译器是否知道翻译
Dim s As String = "test" + "this" + “功能”
到
Dim s As String = "test this function"
从而避免字符串连接对性能的影响?
【问题讨论】:
标签: .net vb.net performance optimization
是的。它确实。我只测试了 VS 2008,但我强烈怀疑以前的版本也是如此。
VB.NET
Public Class Class1
Dim s As String = "test " + "this " + "function"
Public Function test() As String
Return s
End Function
End Class
I.L. - 注意字符串“test this function”
{
.maxstack 8
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: nop
L_0007: ldarg.0
L_0008: ldstr "test this function"
L_000d: stfld string ClassLibrary1.Class1::s
L_0012: nop
L_0013: ret
}
【讨论】:
是的,确实如此!让我们来测试一下。
由于 .NET 将所有托管语言(VB、C#、C++)编译为 IL(中间语言)指令,并且String 类型是 CLS(公共语言规范)的一部分,因此所有 .NET Framework 版本:2.0、3.0、3.5、 4.0 优化了 String 文字连接作为编译过程的一部分。
例如下面的VB.NET代码:
Dim s As String = "A" & "B" & "C"
产生以下 IL 指令:
L_0008: ldstr "ABC"
这清楚地证明了编译器正在优化String字面连接(测试于:ildasm.exe)
但是,如果上面的代码写在单独的语句中:
Dim s As String = "A"
s &= "B"
s &= "C"
没有进行优化,String 连接在运行时执行(性能开销)。这同样适用于在运行时解析数据的单行语句(变量、属性、方法)。
使用下划线 _ 将以上语句连接成一个语句来强制优化:
Dim s As String = "A" _
& "B" _
& "C" _
如果您需要在标记之间换行,请使用vbCrLf(编译时)常量来确保优化,因为使用Environment.NewLine(运行时)属性不会提供任何优化。
希望这可以帮助您在性能上取得优势!
【讨论】:
在我查找时,here's the download page for the spec。
第 11.2 节看起来会是正确的位 - 它基本上相当于 C# 3.0 规范中的 7.18 - 但它不包含相同的保证。我怀疑编译器仍然会这样做,但我看不到任何保证。不过我会再看看。
第 11.2 节确实声明“常量表达式是一个表达式其值可以在编译时完全评估”(我的重点)但我看不出它实际上能保证它将在编译时对其进行全面评估。坦率地说,根据这个条件来做一个表达类别但没有实际使用它是很奇怪的。
快速测试表明,当前的 VB 编译器确实在编译时进行了连接,但如果这是有意的话,规范中确实应该保证。
第 7.3 节更进一步:
当表达式的操作数是 所有原始类型常量,它是 编译器可以评估 编译时的表达式。这样的 表达式被称为常量 表达。
现在,就 CLR 而言,String 不是原始类型(Type.IsPrimitive 将返回 false),但就 VB 规范而言,它是。
它仍然没有说它会评估它...
【讨论】:
编译器将在适当的时候优化字符串连接。但是,如果您不知道可能有多少个连接,则应该考虑使用 StringBuilder 类。
http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx
来自以上文章:
连接的性能 字符串操作或 StringBuilder 对象取决于如何 经常发生内存分配。一种 字符串连接操作总是 分配内存,而 StringBuilder 连接操作 仅在 StringBuilder 对象缓冲区太 小以容纳新数据。 因此,String 类是 更适合串联 如果是固定数量的String,则操作 对象被连接起来。在那里面 情况下,单独的串联 操作甚至可以合并为 编译器的单个操作。一种 StringBuilder 对象更适合于 一个连接操作,如果 任意数量的字符串是 串联;例如,如果一个循环 连接一个随机数 用户输入的字符串。
【讨论】:
Jeff Atwood 对此进行了研究并发表了博文。结果?
【讨论】: