剛開始看到這個標題,估計很多人都雲裡霧裡的。
請看下面兩段:
第一種方式:
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關鍵字效率明顯偏高,隊列中緩存數據明顯大減,而且基本不再出現容器不足溢出現象,這是為什麼呢?答案馬上揭曉。
以下是通過反匯編工具所得的一種類似匯編語言(如果以下真是匯編語言,就當我前面"類似"兩字說錯了,跟我當初學的匯編語言不一樣。這個應該是.net架構可識別的中間語言)
.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,多出很多行相對來說算是賦址操作。這就是導致方法二效率低的主要原因。
但是剛剛我們也提到了,雖然方法一和方法二實現相同的功能,但是方法二帶著套比較保險,即便我們失手,不會制造出垃圾來。即使是你忘記使用.close()、.dispose()方法釋放資源,using還是會自動幫你處理好你遺忘的的壞事。
所以在一般不要求高效開發中,盡量使用using,但是在處理高並發、海量數據等等情況下,盡量不要讓using出現。不過現在好了,自從接觸erlang後,它處理消息確實比C#/java/C++高效多了。
還有一點忘記說了,我用消息泵處理消息隊列,消息泵放到一個using裡面,這會導致所有消息都會在這個using包裹中處理。
這一段是我補充上來的,因為有位大大說了一個非常准確的話,當時我寫貼太快,沒有深思,這次做下補充。
#7樓 2014-10-23 21:59 eflay try catch 如果沒有捕獲到異常的話,是幾乎不會降低速度的,另外,調用了close就不需要dispose了,所以總覺得對你所謂的效率差距保持懷疑。 #10樓[樓主] 2014-10-24 09:07 小堯弟 @eflay
在以下的文章中,我將以“辦公自動化”系統為例,探討如何在有著1000萬條數據的MS SQL SERVER數據庫中實現快速的數據提取和數據分頁。以下代碼說明了我們實例中數據庫的“紅頭文件”一表的部分數據結構:
CREATE TABLE [dbo].[TGongwen] ( --TGongwen是紅頭文件表名
[Gid] [int] IDENTITY (1, 1) NOT NULL ,
--本表的id號,也是主鍵
[title] [varchar] (80) COLLATE Chinese_PRC_CI_AS NULL ,
--紅頭文件的標題
[fariqi] [datetime] NULL ,
--發布日期
[neibuYonghu] [varchar] (70) COLLATE Chinese_PRC_CI_AS NULL ,
--發布用戶
[reader] [varchar] (900) COLLATE Chinese_PRC_CI_AS NULL ,
--需要浏覽的用戶。每個用戶中間用分隔符“,”分開
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
下面,我們來往數據庫中添加1000萬條數據:
declare @i int
set @i=1
while @i<=250000
begin
insert into Tgongwen(fariqi,neibuyonghu,reader,title) values('2004-2-5','通信科','通信科,辦公室,王局長,劉局長,張局長,admin,刑偵支隊,特勤支隊,交巡警支隊,經偵支隊,戶政科,治安支隊,外事科','這是最先的25萬條記錄')
set @i=@i+1
end
GO
declare @i int
set @i=1
while @i<=250000
begin
insert into Tgongwen(fariqi,neibuyonghu,reader,title) values('2004-9-16','辦公室','辦公室,通信科,王局長,劉局長,張局長,admin,刑偵支隊,特勤支隊,交巡警支隊,經偵支隊,戶政科,外事科','這是中間的25萬條記錄')
set @i=@i+1
end
GO
declare @h int
set @h=1
while @h<=100
begin
declare @i int
set @i=2002
while @i<=2003
begin
declare @j int
set @j=0
while @j<50
begin
declare @k int
set @k=0
while @k<50
begin
insert into Tgongwen(fariqi,neibuyonghu,reader,title) values(cast(@i as varchar(4))+'-8-15 3:'+cast(@j as varchar(2))+':'+cast(@j as varchar(2)),'通信科','辦公室,通信科,王......余下全文>>
去51cto網上博客搜索看吧,也有很多類似的書籍