分析编译的MSIL(第二部分)
这是一个后续的文章中()我以为我想探讨编译器如何工作的整体概念,什么是不同的语言产生。我以为我会探讨如何优化使用。NET框架提供的共同对象的代码。这个概念
应用从以前的文章进行了更新。NET框架的StringBuilder类的使用。这主要是来说明这个类执行字符串串联效率。经常有人建议使用字符串生成器类的字符串串联工作,但我想知道是否有人实际看到这个类提供的效率的证明。
本文遵循一些额外的优化技术与VB应用程序处理。这些技术/测试包括改变默认的模块,由VS.NET提供的一类,只是为了看看编译器看到两个类之间的差异。我也改变了几个项目的设置。虽然不是一种优化技术,但更多的测试,看看是否有实际上是在VB编译器的类和模块之间的任何差异,我决定改变从模块Module1的默认类的声明在项目属性的编译选项卡移除整数溢出检查(这可以找到"高级设置"下)交换股权严
要真正测试这些优化,我想我让这两种方法一起运行,并打印出控制台,所花费的时间长短来处理只是比较所花费多长时间。我想我也改变旧的应用程序的每一个项目,并提供空引号,即改变"strSomeString"变量的声明","使用。NET框架的string.empty。这主要是由编译器生成。"守则"VB
C#中{C}J#<code>Imports System.Diagnostics
Class Module1
Shared Sub Main()
Dim sbSomeString As New System.Text.StringBuilder
Dim sw As New Stopwatch
sw.Start()
For i As Integer = 0 To 1000
sbSomeString.Append("Test ")
Next
sw.Stop()
Console.WriteLine(sbSomeString.ToString)
Console.WriteLine("Time Taken :" & sw.ElapsedMilliseconds)
OldCode()
End Sub
Shared Sub OldCode()
Dim strSomeString As String = String.Empty
Dim sw As New Stopwatch
sw.Start()
For i As Integer = 0 To 1000
strSomeString += "Test "
Next
sw.Stop()
Console.WriteLine(strSomeString)
Console.WriteLine("Time Taken :" & sw.ElapsedMilliseconds)
Console.ReadLine()
End Sub
End Class
彗星<code>package ConsoleJSharp;
import System.*;
import System.Diagnostics.*;
public class Program
{
public static void main(String[] args)
{
System.Text.StringBuilder sbSomeString = new System.Text.StringBuilder();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
sbSomeString.Append("Test ");
}
sw.Stop();
Console.WriteLine(sbSomeString.ToString());
Console.WriteLine("Time Taken :" + sw.get_ElapsedMilliseconds());
OldCode();
}
public static void OldCode()
{
String strSomeString = String.Empty;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
strSomeString += "Test ";
}
sw.Stop();
Console.WriteLine(strSomeString);
Console.WriteLine("Time Taken :" + sw.get_ElapsedMilliseconds());
Console.ReadLine();
}
}
在MSILVB
<code>
#include "stdafx.h"
#using <mscorlib.dll>
using namespace System;
using namespace System::Diagnostics;
void OldCode();
int main(array<System::String ^> ^args)
{
System::Text::StringBuilder^ sbSomeString = gcnew System::Text::StringBuilder();
Stopwatch^ sw = gcnew Stopwatch;
sw->Start();
for (int i = 0;i< 1000 ;i++)
{
sbSomeString->Append("Test ");
}
sw->Stop();
Console::WriteLine(sbSomeString->ToString());
Console::WriteLine("Time Taken :" + sw->ElapsedMilliseconds);
OldCode();
return 0;
}
void OldCode()
{
String^ strSomeString = String::Empty;
Stopwatch^ sw = gcnew Stopwatch;
sw->Start();
for (int i = 0;i< 1000 ;i++)
{
strSomeString += "Test ";
}
sw->Stop();
Console::WriteLine(strSomeString);
Console::WriteLine("Time Taken :" + sw->ElapsedMilliseconds);
Console::ReadLine();
}
C#中<code>
.method public static void Main() cil managed
{
.entrypoint
.custom instance
void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 103 (0x67)
.maxstack 2
.locals init ([0] class [mscorlib]System.Text.StringBuilder sbSomeString,
[1] class [System]System.Diagnostics.Stopwatch sw,
[2] int32 i,
[3] int32 VB$CG$t_i4$S0)
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_0006: stloc.0
IL_0007: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0013: nop
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: ldloc.0
IL_0017: ldstr "Test "
IL_001c: callvirt instance class [mscorlib]System.Text.StringBuilder
[mscorlib]System.Text.StringBuilder::Append(string)
IL_0021: pop
IL_0022: nop
IL_0023: ldloc.2
IL_0024: ldc.i4.1
IL_0025: add.ovf
IL_0026: stloc.2
IL_0027: ldloc.2
IL_0028: ldc.i4 0x3e8
IL_002d: stloc.3
IL_002e: ldloc.3
IL_002f: ble.s IL_0016
IL_0031: ldloc.1
IL_0032: callvirt
instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0037: nop
IL_0038: ldloc.0
IL_0039: callvirt
instance string [mscorlib]System.Text.StringBuilder::ToString()
IL_003e: call void [mscorlib]System.Console::WriteLine(string)
IL_0043: nop
IL_0044: ldstr "Time Taken :"
IL_0049: ldloc.1
IL_004a: callvirt instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_004f: call string
[Microsoft.VisualBasic]
Microsoft.VisualBasic.CompilerServices.Conversions::ToString(int64)
IL_0054: call string [mscorlib]System.String::Concat(string,
string)
IL_0059: call void [mscorlib]System.Console::WriteLine(string)
IL_005e: nop
IL_005f: call void VBConsole.Module1::OldCode()
IL_0064: nop
IL_0065: nop
IL_0066: ret
} // end of method Module1::Main
.method public static void OldCode() cil managed
{
// Code size 98 (0x62)
.maxstack 2
.locals init ([0] string strSomeString,
[1] class [System]System.Diagnostics.Stopwatch sw,
[2] int32 i,
[3] int32 VB$CG$t_i4$S0)
IL_0000: nop
IL_0001: ldsfld string [mscorlib]System.String::Empty
IL_0006: stloc.0
IL_0007: newobj instance void
[System]System.Diagnostics.Stopwatch::.ctor()
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: callvirt instance void
[System]System.Diagnostics.Stopwatch::Start()
IL_0013: nop
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: ldloc.0
IL_0017: ldstr "Test "
IL_001c: call string [mscorlib]System.String::Concat(string,
string)
IL_0021: stloc.0
IL_0022: nop
IL_0023: ldloc.2
IL_0024: ldc.i4.1
IL_0025: add.ovf
IL_0026: stloc.2
IL_0027: ldloc.2
IL_0028: ldc.i4 0x3e8
IL_002d: stloc.3
IL_002e: ldloc.3
IL_002f: ble.s IL_0016
IL_0031: ldloc.1
IL_0032: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0037: nop
IL_0038: ldloc.0
IL_0039: call void [mscorlib]System.Console::WriteLine(string)
IL_003e: nop
IL_003f: ldstr "Time Taken :"
IL_0044: ldloc.1
IL_0045: callvirt instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_004a: call string [Microsoft.VisualBasic]
Microsoft.VisualBasic.CompilerServices.Conversions::ToString(int64)
IL_004f: call string [mscorlib]System.String::Concat(string,
string)
IL_0054: call void [mscorlib]System.Console::WriteLine(string)
IL_0059: nop
IL_005a: call string [mscorlib]System.Console::ReadLine()
IL_005f: pop
IL_0060: nop
IL_0061: ret
} // end of method Module1::OldCode
J#<code>
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 107 (0x6b)
.maxstack 2
.locals init ([0] class [mscorlib]System.Text.StringBuilder sbSomeString,
[1] class [System]System.Diagnostics.Stopwatch sw,
[2] int32 i,
[3] bool CS$4$0000)
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_0006: stloc.0
IL_0007: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0013: nop
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: br.s IL_002a
IL_0018: nop
IL_0019: ldloc.0
IL_001a: ldstr "Test "
IL_001f: callvirt instance class
[mscorlib]System.Text.StringBuilder
[mscorlib]System.Text.StringBuilder::Append(string)
IL_0024: pop
IL_0025: nop
IL_0026: ldloc.2
IL_0027: ldc.i4.1
IL_0028: add
IL_0029: stloc.2
IL_002a: ldloc.2
IL_002b: ldc.i4 0x3e8
IL_0030: clt
IL_0032: stloc.3
IL_0033: ldloc.3
IL_0034: brtrue.s IL_0018
IL_0036: ldloc.1
IL_0037: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_003c: nop
IL_003d: ldloc.0
IL_003e: callvirt instance string [mscorlib]System.Object::ToString()
IL_0043: call void [mscorlib]System.Console::WriteLine(string)
IL_0048: nop
IL_0049: ldstr "Time Taken :"
IL_004e: ldloc.1
IL_004f: callvirt instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_0054: box [mscorlib]System.Int64
IL_0059: call string [mscorlib]System.String::Concat(object,
object)
IL_005e: call void [mscorlib]System.Console::WriteLine(string)
IL_0063: nop
IL_0064: call void ConsoleCSharp.Program::OldCode()
IL_0069: nop
IL_006a: ret
} // end of method Program::Main
.method private hidebysig static void OldCode() cil managed
{
// Code size 102 (0x66)
.maxstack 2
.locals init ([0] string strSomeString,
[1] class [System]System.Diagnostics.Stopwatch sw,
[2] int32 i,
[3] bool CS$4$0000)
IL_0000: nop
IL_0001: ldsfld string [mscorlib]System.String::Empty
IL_0006: stloc.0
IL_0007: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0013: nop
IL_0014: ldc.i4.0
IL_0015: stloc.2
IL_0016: br.s IL_002a
IL_0018: nop
IL_0019: ldloc.0
IL_001a: ldstr "Test "
IL_001f: call string [mscorlib]System.String::Concat(string,
string)
IL_0024: stloc.0
IL_0025: nop
IL_0026: ldloc.2
IL_0027: ldc.i4.1
IL_0028: add
IL_0029: stloc.2
IL_002a: ldloc.2
IL_002b: ldc.i4 0x3e8
IL_0030: clt
IL_0032: stloc.3
IL_0033: ldloc.3
IL_0034: brtrue.s IL_0018
IL_0036: ldloc.1
IL_0037: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_003c: nop
IL_003d: ldloc.0
IL_003e: call void [mscorlib]System.Console::WriteLine(string)
IL_0043: nop
IL_0044: ldstr "Time Taken :"
IL_0049: ldloc.1
IL_004a: callvirt instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_004f: box [mscorlib]System.Int64
IL_0054: call string [mscorlib]System.String::Concat(object,
object)
IL_0059: call void [mscorlib]System.Console::WriteLine(string)
IL_005e: nop
IL_005f: call string [mscorlib]System.Console::ReadLine()
IL_0064: pop
IL_0065: ret
} // end of method Program::OldCode
彗星<code>
.method public hidebysig static void main(string[] args) cil managed
{
.entrypoint
// Code size 122 (0x7a)
.maxstack 2
.locals init ([0] class [mscorlib]System.Text.StringBuilder sbSomeString,
[1] class [System]System.Diagnostics.Stopwatch sw,
[2] int32 i)
IL_0000: ldtoken [vjslib]com.ms.vjsharp.lang.ObjectImpl
IL_0005: call void
[mscorlib] System.Runtime.CompilerServices.
RuntimeHelpers::RunClassConstructor
(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_000a: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_000f: stloc.0
IL_0010: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_001c: ldc.i4.0
IL_001d: stloc.2
IL_001e: br.s IL_0030
IL_0020: ldloc.0
IL_0021: ldstr "Test "
IL_0026: callvirt instance class [mscorlib]System.Text.StringBuilder
[mscorlib]System.Text.StringBuilder::Append(string)
IL_002b: pop
IL_002c: ldloc.2
IL_002d: ldc.i4.1
IL_002e: add
IL_002f: stloc.2
IL_0030: ldloc.2
IL_0031: ldc.i4 0x3e8
IL_0036: blt.s IL_0020
IL_0038: ldloc.1
IL_0039: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_003e: ldloc.0
IL_003f: callvirt instance string [mscorlib]System.Text.StringBuilder::ToString()
IL_0044: call void [mscorlib]System.Console::WriteLine(string)
IL_0049: newobj instance void [vjslib]java.lang.StringBuffer::.ctor()
IL_004e: ldstr "Time Taken :"
IL_0053: callvirt instance class
[vjslib]java.lang.StringBuffer
[vjslib]java.lang.StringBuffer::append(string)
IL_0058: ldloc.1
IL_0059: callvirt instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_005e: callvirt instance class
[vjslib]java.lang.StringBuffer
[vjslib]java.lang.StringBuffer::append(int64)
IL_0063: callvirt instance string [vjslib]java.lang.StringBuffer::ToString()
IL_0068: call void [mscorlib]System.Console::WriteLine(string)
IL_006d: call void ConsoleJSharp.Program::OldCode()
IL_0072: call void
[vjslib]com.ms.vjsharp.util.Utilities::cleanupAfterMainReturns()
IL_0077: br.s IL_0079
IL_0079: ret
} // end of method Program::main
.method public hidebysig static void OldCode() cil managed
{
// Code size 118 (0x76)
.maxstack 2
.locals init ([0] string strSomeString,
[1] class [System]System.Diagnostics.Stopwatch sw,
[2] int32 i)
IL_0000: ldsfld string [mscorlib]System.String::Empty
IL_0005: stloc.0
IL_0006: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0012: ldc.i4.0
IL_0013: stloc.2
IL_0014: br.s IL_0035
IL_0016: newobj instance void [vjslib]java.lang.StringBuffer::.ctor()
IL_001b: ldloc.0
IL_001c: callvirt instance class [vjslib] java.lang.StringBuffer
[vjslib]java.lang.StringBuffer::append(string)
IL_0021: ldstr "Test "
IL_0026: callvirt instance class [vjslib]java.lang.StringBuffer
[vjslib]java.lang.StringBuffer::append(string)
IL_002b: callvirt instance string [vjslib]java.lang.StringBuffer::ToString()
IL_0030: stloc.0
IL_0031: ldloc.2
IL_0032: ldc.i4.1
IL_0033: add
IL_0034: stloc.2
IL_0035: ldloc.2
IL_0036: ldc.i4 0x3e8
IL_003b: blt.s IL_0016
IL_003d: ldloc.1
IL_003e: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0043: ldloc.0
IL_0044: call void [mscorlib]System.Console::WriteLine(string)
IL_0049: newobj instance void [vjslib]java.lang.StringBuffer::.ctor()
IL_004e: ldstr "Time Taken :"
IL_0053: callvirt instance class [vjslib]java.lang.StringBuffer
[vjslib]java.lang.StringBuffer::append(string)
IL_0058: ldloc.1
IL_0059: callvirt instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_005e: callvirt instance class
[vjslib]java.lang.StringBuffer
[vjslib]java.lang.StringBuffer::append(int64)
IL_0063: callvirt instance string [vjslib]java.lang.StringBuffer::ToString()
IL_0068: call void [mscorlib]System.Console::WriteLine(string)
IL_006d: call string [mscorlib]System.Console::ReadLine()
IL_0072: pop
IL_0073: br.s IL_0075
IL_0075: ret
} // end of method Program::OldCode
结论<code>
.method assembly static int32 main(string[] args) cil managed
{
// Code size 106 (0x6a)
.maxstack 2
.locals ([0] class [System]System.Diagnostics.Stopwatch sw,
[1] int32 i,
[2] class [mscorlib]System.Text.StringBuilder sbSomeString,
[3] int32 V_3)
IL_0000: ldc.i4.0
IL_0001: stloc.3
IL_0002: ldnull
IL_0003: stloc.2
IL_0004: ldnull
IL_0005: stloc.0
IL_0006: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_000b: stloc.2
IL_000c: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: call instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0018: ldc.i4.0
IL_0019: stloc.1
IL_001a: br.s IL_0020
IL_001c: ldloc.1
IL_001d: ldc.i4.1
IL_001e: add
IL_001f: stloc.1
IL_0020: ldloc.1
IL_0021: ldc.i4 0x3e8
IL_0026: bge.s IL_0036
IL_0028: ldloc.2
IL_0029: ldstr "Test "
IL_002e: call instance class
[mscorlib]System.Text.StringBuilder
[mscorlib]System.Text.StringBuilder::Append(string)
IL_0033: pop
IL_0034: br.s IL_001c
IL_0036: ldloc.0
IL_0037: call instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_003c: ldloc.2
IL_003d: callvirt instance string [mscorlib]System.Text.StringBuilder::ToString()
IL_0042: call void [mscorlib]System.Console::WriteLine(string)
IL_0047: ldstr "Time Taken :"
IL_004c: ldloc.0
IL_004d: call instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_0052: box [mscorlib]System.Int64
IL_0057: call string [mscorlib]System.String::Concat(object,
object)
IL_005c: call void [mscorlib]System.Console::WriteLine(string)
IL_0061: call void modopt( [mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
OldCode()
IL_0066: ldc.i4.0
IL_0067: stloc.3
IL_0068: ldloc.3
IL_0069: ret
} // end of method 'Global Functions'::main
.method assembly static void modopt ([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
OldCode() cil managed
{
.vtentry 1 : 1
// Code size 97 (0x61)
.maxstack 2
.locals ([0] class [System]System.Diagnostics.Stopwatch sw,
[1] string strSomeString,
[2] int32 i)
IL_0000: ldnull
IL_0001: stloc.1
IL_0002: ldnull
IL_0003: stloc.0
IL_0004: ldsfld string [mscorlib]System.String::Empty
IL_0009: stloc.1
IL_000a: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: call instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0016: ldc.i4.0
IL_0017: stloc.2
IL_0018: br.s IL_001e
IL_001a: ldloc.2
IL_001b: ldc.i4.1
IL_001c: add
IL_001d: stloc.2
IL_001e: ldloc.2
IL_001f: ldc.i4 0x3e8
IL_0024: bge.s IL_0034
IL_0026: ldloc.1
IL_0027: ldstr "Test "
IL_002c: call string [mscorlib]System.String::Concat(string,
string)
IL_0031: stloc.1
IL_0032: br.s IL_001a
IL_0034: ldloc.0
IL_0035: call instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_003a: ldloc.1
IL_003b: call void [mscorlib]System.Console::WriteLine(string)
IL_0040: ldstr "Time Taken :"
IL_0045: ldloc.0
IL_0046: call instance int64
[System]System.Diagnostics.Stopwatch::get_ElapsedMilliseconds()
IL_004b: box [mscorlib]System.Int64
IL_0050: call string [mscorlib]System.String::Concat(object,
object)
IL_0055: call void [mscorlib]System.Console::WriteLine(string)
IL_005a: call string [mscorlib]System.Console::ReadLine()
IL_005f: pop
IL_0060: ret
} // end of method 'Global Functions'::OldCode
我还没有包括所有的编译器生成的汇编代码。我只是我认为这是值得注意的,即我有只包含代码的职能。
有趣的是,需要注意的是StringBuilder类是能够执行字符串串联在0ms,而字符串连接在传统方法需要更长的平均17ms,历史06年6月10日:草案版本1第2部上传06年9月10日:更新的内容,格式和更改过的文章的标题
|三九咨询