I have the following code:
Function StringBuilderModification(s As String) As String
Dim b = New System.Text.StringBuilder(10000)
For i = 0 To s.Length - 1 Step 5
b.Append(s, i, 5)
b.Append("X")
Next
Return b.ToString
End Function
When I call this with a string of 10.000 chars long, it runs for 4741 ticks on VB and for 23471 ticks on Mercury. So Mercury takes 5 times longer somehow.
The IL generated by VB:
.method public static string StringBuilderModification (
string s
) cil managed
{
.locals init (
[0] class [mscorlib]System.Text.StringBuilder b,
[1] int32 V_1,
[2] int32 i
)
IL_0000: ldc.i4 10000
IL_0005: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(int32)
IL_000a: stloc.0
IL_000b: ldarg.0
IL_000c: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_0011: ldc.i4.1
IL_0012: sub.ovf
IL_0013: stloc.1
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: br.s IL_0032
.loop
{
IL_0018: ldloc.0
IL_0019: ldarg.0
IL_001a: ldloc.2
IL_001b: ldc.i4.5
IL_001c: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string, int32, int32)
IL_0021: pop
IL_0022: ldloc.0
IL_0023: ldstr "X"
IL_0028: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
IL_002d: pop
IL_002e: ldloc.2
IL_002f: ldc.i4.5
IL_0030: add.ovf
IL_0031: stloc.2
IL_0032: ldloc.2
IL_0033: ldloc.1
IL_0034: ble.s IL_0018
}
IL_0036: ldloc.0
IL_0037: callvirt instance string [mscorlib]System.Text.StringBuilder::ToString()
IL_003c: ret
}
IL generated by Mercury:
.method public hidebysig static string StringBuilderModification (
string s
) cil managed
{
.locals init (
[0] class [mscorlib]System.Text.StringBuilder V_0,
[1] int32 V_1
)
IL_0000: ldc.i4 10000
IL_0005: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(int32)
IL_000a: stloc.0
IL_000b: ldc.i4.0
IL_000c: stloc.1
IL_000d: br.s IL_0029
.loop
{
IL_000f: ldloc.0
IL_0010: ldarg.0
IL_0011: ldloc.1
IL_0012: ldc.i4.5
IL_0013: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string, int32, int32)
IL_0018: pop
IL_0019: ldloc.0
IL_001a: ldstr "X"
IL_001f: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
IL_0024: pop
IL_0025: ldloc.1
IL_0026: ldc.i4.5
IL_0027: add
IL_0028: stloc.1
IL_0029: ldloc.1
IL_002a: ldarg.0
IL_002b: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_0030: ldc.i4.1
IL_0031: sub
IL_0032: ble.s IL_000f
}
IL_0034: ldloc.0
IL_0035: callvirt instance string [mscorlib]System.Text.StringBuilder::ToString()
IL_003a: ret
}
When I look at the decompiled VB code, I see an optimization that is not done in Mercury:
VB:
Mercury:
What means that s.Length - 1 is calculated in every loop again for the Mercury code, while it is only done once with the VB code.