高併發、海量數據處理儘可能少使用using也能提高效率

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

相關文章
相關標籤/搜索