请看下面两段:html
第一种方式:程序员
MemoryStream stream = new MemoryStream();
string text = "aasasdfasdfad;sas;fkqeworpkqwefkasdjfasdjf"; byte[] buff = System.Text.ASCIIEncoding.ASCII.GetBytes(text); stream.Write(buff, 0, buff.Length); stream.Flush(); stream.Close(); stream.Dispose();
第二种方式:并发
string text = "aasasdfasdfad;sas;fkqeworpkqwefkasdjfasdjf"; using (MemoryStream stream = new MemoryStream()) { byte[] buff = System.Text.ASCIIEncoding.ASCII.GetBytes(text); stream.Write(buff, 0, buff.Length); stream.Flush(); stream.Close(); }
不单单是我,估计一个老鸟程序员,大都会选择方法二,虽然方法一和方法二实现相同的功能,可是方法二带着套比较保险,即使咱们失手,不会制造出垃圾来(这话听着怪怪的,能理解我在说什么就好)。以后,我在作一些消息处理机制的接收、处理、分发测试中,发现使用using关键字和不用using关键字,效率有着很大差别,不使用using关键字效率明显偏高,MQ队列占用明显偏小,这是为何呢?答案立刻揭晓。ide
如下是经过反汇编工具所得的中间语言(IL)高并发
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代码大小 65 (0x41) .maxstack 4 .locals init ([0] string text, [1] class [mscorlib]System.IO.MemoryStream 'stream', [2] uint8[] buff) IL_0000: nop IL_0001: ldstr "aasasdfasdfad;sas;fkqeworpkqwefkasdjfasdjf" IL_0006: stloc.0 IL_0007: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor() IL_000c: stloc.1 IL_000d: call class [mscorlib]System.Text.Encoding [mscorlib]System.Text.Encoding::get_ASCII() IL_0012: ldloc.0 IL_0013: callvirt instance uint8[] [mscorlib]System.Text.Encoding::GetBytes(string) IL_0018: stloc.2 IL_0019: ldloc.1 IL_001a: ldloc.2 IL_001b: ldc.i4.0 IL_001c: ldloc.2 IL_001d: ldlen IL_001e: conv.i4 IL_001f: callvirt instance void [mscorlib]System.IO.Stream::Write(uint8[], int32, int32) IL_0024: nop IL_0025: ldloc.1 IL_0026: callvirt instance void [mscorlib]System.IO.Stream::Flush() IL_002b: nop IL_002c: ldloc.1 IL_002d: callvirt instance void [mscorlib]System.IO.Stream::Close() IL_0032: nop IL_0033: ldloc.1 IL_0034: callvirt instance void [mscorlib]System.IO.Stream::Dispose() IL_0039: nop IL_0040: ret } // end of method Program::Main
以上是方法一,所得中间语言,看起来很是干净、流畅。下面看看方法二的:工具
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代码大小 79 (0x4f) .maxstack 4 .locals init ([0] string text, [1] class [mscorlib]System.IO.MemoryStream 'stream', [2] uint8[] buff, [3] bool CS$4$0000) IL_0000: nop IL_0001: ldstr "aasasdfasdfad;sas;fkqeworpkqwefkasdjfasdjf" IL_0006: stloc.0 IL_0007: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor() IL_000c: stloc.1 .try { IL_000d: nop IL_000e: call class [mscorlib]System.Text.Encoding [mscorlib]System.Text.Encoding::get_ASCII() IL_0013: ldloc.0 IL_0014: callvirt instance uint8[] [mscorlib]System.Text.Encoding::GetBytes(string) IL_0019: stloc.2 IL_001a: ldloc.1 IL_001b: ldloc.2 IL_001c: ldc.i4.0 IL_001d: ldloc.2 IL_001e: ldlen IL_001f: conv.i4 IL_0020: callvirt instance void [mscorlib]System.IO.Stream::Write(uint8[], int32, int32) IL_0025: nop IL_0026: ldloc.1 IL_0027: callvirt instance void [mscorlib]System.IO.Stream::Flush() IL_002c: nop IL_002d: ldloc.1 IL_002e: callvirt instance void [mscorlib]System.IO.Stream::Close() IL_0033: nop IL_0034: nop IL_0035: leave.s IL_0047 } // end .try finally { IL_0037: ldloc.1 IL_0038: ldnull IL_0039: ceq IL_003b: stloc.3 IL_003c: ldloc.3 IL_003d: brtrue.s IL_0046 IL_003f: ldloc.1 IL_0040: callvirt instance void [mscorlib]System.IDisposable::Dispose() IL_0045: nop IL_0046: endfinally } // end handler IL_0047: pop IL_0048: ret } // end of method Program::Main
第二段IL中间红色部分即为不一样测试
[3] bool CS$4$0000) IL_000d: nop 中止几个时钟周期 IL_000d: nop IL_0035: leave.s IL_0047 退出受保护的代码区域,无条件将控制转移到目标指令 IL_0038: ldnull 将空引用(O 类型)推送到计算堆栈上 IL_0039: ceq 比较两个值。若是这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;不然,将 0 (int32) 推送到计算堆栈上 IL_003b: stloc.3 从计算堆栈的顶部弹出当前值并将其存储到索引 3 处的局部变量列表中 IL_003c: ldloc.3 将索引 3 处的局部变量加载到计算堆栈上 IL_003d: brtrue.s IL_0046 若是 value 为 true、非空或非零,则将控制转移到目标指令 IL_003f: ldloc.1 将索引 1 处的局部变量加载到计算堆栈上 IL_0045: nop IL_0046: endfinally 将控制从异常块的 fault 或 finally 子句转移回公共语言结构 (CLI) 异常处理程序
IL指令汇总优化
可是刚刚咱们也提到了,虽然方法一和方法二实现相同的功能,可是方法二带着套比较保险,即使咱们失手,不会制造出垃圾来。即便是你忘记使用.close()、.dispose()方法释放资源,using仍是会自动帮你处理好你遗忘的的坏事。ui
因此在通常不要求高效开发中,尽可能使用using,可是在处理高并发、海量数据等等状况下,尽可能不要让using出现。spa
提示:
try..catch有必定的代码优化能力,少许代码测试,try..catch可能更优