請看下面兩段: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可能更優