剛開始看到這個標題,估計很多人都云里霧里的。
請看下面兩段:
第一種方式:
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(); }不僅僅是我,估計一個老鳥程序員,大都會選擇方法二,雖然方法一和方法二實現(xiàn)相同的功能,但是方法二帶著套比較保險,即便我們失手,不會制造出垃圾來(這話聽著怪怪的,能理解我在說什么就好)。之后,我在做一些消息處理機制的接收、處理、分發(fā)測試中,發(fā)現(xiàn)使用using關(guān)鍵字和不用using關(guān)鍵字,效率有著很大差異,不使用using關(guān)鍵字效率明顯偏高,隊列中緩存數(shù)據(jù)明顯大減,而且基本不再出現(xiàn)容器不足溢出現(xiàn)象,這是為什么呢?答案馬上揭曉。
以下是通過反匯編工具所得的一種類似匯編語言(如果以下真是匯編語言,就當我前面"類似"兩字說錯了,跟我當初學的匯編語言不一樣。這個應該是.net架構(gòu)可識別的中間語言)
.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(紅字部分)這下能看出問題來了吧,本來是功能相同的兩段代碼,但是在方法二中,多出了一個try..finally模塊,多出一個初始存儲元的申請CS$4$0000,多出很多行相對來說算是賦址操作。這就是導致方法二效率低的主要原因。(刪除這段的原因是大家都拿著我給的例子測試,其實我只是把一個大的功能縮小到這么小,來說明一個問題)
但是剛剛我們也提到了,雖然方法一和方法二實現(xiàn)相同的功能,但是方法二帶著套比較保險,即便我們失手,不會制造出垃圾來。即使是你忘記使用.close()、.dispose()方法釋放資源,using還是會自動幫你處理好你遺忘的的壞事。
所以在一般不要求高效開發(fā)中,盡量使用using,但是在處理高并發(fā)、海量數(shù)據(jù)等等情況下,盡量不要讓using出現(xiàn)。不過現(xiàn)在好了,自從接觸erlang后,它處理消息確實比C#/java/C++高效多了。
try..catch有一定的代碼優(yōu)化能力,少量代碼測試,try..catch可能更優(yōu)
新聞熱點
疑難解答