2010-09-02 27 views
6

Đây là một câu hỏi followup để thisĐó là nhanh hơn - Một Sử dụng chặn hoặc try/catch/Cuối cùng

Tôi có nên gắn bó với try/catch/Cuối cùng xây dựng, hoặc đi với Sử dụng xây dựng?

mẫu mã cho try/catch/Cuối cùng:

Dim oRequest As WebRequest 
Dim oResponse As HttpWebResponse = Nothing 
Dim dataStream As Stream = Nothing 
Dim reader As StreamReader = Nothing 
Dim responseFromServer As String 

Try 
     sNewCustomerURL = NewCustomerQueryStringPrepare() 

    'make the call to the webservice to add a new customer 
    oRequest = WebRequest.Create(sNewCustomerURL) 

    oRequest = CType(oRequesC, HttpWebRequest) 
    oRequest.Method = "GET" 
    oResponse = CType(oRequest.GetResponse(), HttpWebResponse) 

    dataStream = oResponse.GetResponseStream() 
    reader = New StreamReader(dataStream) 
    responseFromServer = reader.ReadToEnd() 

     Dim xml As New XmlDocument() 
    xml.LoadXml(responseFromServer) 
    Dim node As XmlNodeList = xml.GetElementsByTagName("SUCCESS") 
    Dim value = CBool(node(0).InnerText) 

    'do stuff    


Catch ex As Exception 

     'process exception 

Finally 

    'do cleanup 
    oRequest = Nothing 
    If Not oResponse Is Nothing Then 
     oResponse.Close() 
    End If 
    oResponse = Nothing 
    If Not reader Is Nothing Then 
     reader.Close() 
    End If 
    reader = Nothing 
    If Not dataStream Is Nothing Then 
     dataStream.Flush() 
     dataStream.Close() 
    End If 
    dataStream = Nothing 
End Try 

Tôi biết những gì mã sẽ cần phải được cho dùng xây dựng. Tôi chỉ muốn biết nếu sử dụng cấu trúc Sử dụng sẽ nhanh hơn so sánh chu kỳ đồng hồ.

+11

Lệnh 'thẻ using' nhanh hơn nhiều . Đã lưu tôi khoảng 5 giây khi nhập. – tidwall

Trả lời

9

Sẽ không có sự khác biệt về hiệu suất. using được mở rộng bởi trình biên dịch thành khối thử/cuối cùng.

Bạn sẽ thấy rằng hai phương pháp sau đây biên dịch thành IL giống hệt nhau.

void SampleWithUsing() 
{ 
    using (MemoryStream s = new MemoryStream()) 
    { 
     s.WriteByte(1); 
    } 
} 

void SampleWithTryFinally() 
{ 
    MemoryStream s = new MemoryStream(); 
    try 
    { 
     s.WriteByte(1); 
    } 
    finally 
    { 
     if (s != null) s.Dispose(); 
    } 
} 

Các IL được tạo ra trong trường hợp đầu tiên là:

 
.method private hidebysig instance void SampleWithUsing() cil managed 
{ 
    // Code size  26 (0x1a) 
    .maxstack 2 
    .locals init ([0] class [mscorlib]System.IO.MemoryStream s) 
    IL_0000: newobj  instance void [mscorlib]System.IO.MemoryStream::.ctor() 
    IL_0005: stloc.0 
    .try 
    { 
    IL_0006: ldloc.0 
    IL_0007: ldc.i4.1 
    IL_0008: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8) 
    IL_000d: leave.s IL_0019 
    } // end .try 
    finally 
    { 
    IL_000f: ldloc.0 
    IL_0010: brfalse.s IL_0018 
    IL_0012: ldloc.0 
    IL_0013: callvirt instance void [mscorlib]System.IDisposable::Dispose() 
    IL_0018: endfinally 
    } // end handler 
    IL_0019: ret 
} // end of method Program::SampleWithUsing 

Trong trường hợp thứ hai với một thử/cuối cùng trong C# chúng tôi nhận được:

 
.method private hidebysig instance void SampleWithTryFinally() cil managed 
{ 
    // Code size  26 (0x1a) 
    .maxstack 2 
    .locals init ([0] class [mscorlib]System.IO.MemoryStream s) 
    IL_0000: newobj  instance void [mscorlib]System.IO.MemoryStream::.ctor() 
    IL_0005: stloc.0 
    .try 
    { 
    IL_0006: ldloc.0 
    IL_0007: ldc.i4.1 
    IL_0008: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8) 
    IL_000d: leave.s IL_0019 
    } // end .try 
    finally 
    { 
    IL_000f: ldloc.0 
    IL_0010: brfalse.s IL_0018 
    IL_0012: ldloc.0 
    IL_0013: callvirt instance void [mscorlib]System.IO.Stream::Dispose() 
    IL_0018: endfinally 
    } // end handler 
    IL_0019: ret 
} // end of method Program::SampleWithTryFinally 
+0

Bạn đang thiếu thông tin trong đó. – tidwall

+0

@jojaba: Vâng, tôi quyết định đi mà không nắm bắt trong ví dụ cho sự đơn giản. Nếu bạn mong đợi phần thân của câu lệnh dùng để ném bạn có thể thêm một lần thử/bắt. Nhưng xin lưu ý rằng để so sánh công bằng, bạn sẽ phải thêm phần đánh bắt vào cả hai phương pháp, tức là thêm một bản đánh bắt vào phiên bản thử/cuối cùng * và * thêm một khối try/catch bên trong hoặc bên ngoài câu lệnh sử dụng. –

0

Tôi phải tin rằng việc sử dụng so với try/catch sẽ không làm cho bất kỳ hiệu suất khác biệt nào liên quan đến mã bạn đang chạy bên trong các cấu trúc đó.

2

using biên dịch thành try/catch/finally. Tôi thực sự không thể thấy có bất kỳ sự khác biệt ngữ nghĩa hay hiệu suất nào, miễn là bạn vứt bỏ đúng đối tượng của mình trong trường hợp của một hướng dẫn sử dụng try/catch.

Trong bất kỳ trường hợp nào, hãy truy cập using, xem như nó dọn dẹp tự động (thực tế trong mệnh đề finally) cho bạn. Ngay cả khi có sự khác biệt về hiệu suất, rất có thể bạn sẽ có những nơi tốt hơn để tối ưu hóa.

0

Thử/Bắt/Cuối cùng nhanh hơn.

1) 6,638 giây: sử dụng thẻ
2) 6,265 giây: try/catch/finally

Tôi chạy này khoảng một chục lần. Hãy thử/Catch/Cuối cùng luôn luôn xuất hiện trên đầu trang.

DateTime start = DateTime.Now; 
for (int i = 0; i < 50000000; i++) 
{ 
    using (MemoryStream s = new MemoryStream()) 
    { 
     s.WriteByte(1); 
    } 
} 
Console.WriteLine(DateTime.Now.Subtract(start) + " seconds"); 
start = DateTime.Now; 
for (int i = 0; i < 50000000; i++) 
{ 
    MemoryStream s = null; 
    try 
    { 
     s = new MemoryStream(); 
     s.WriteByte(1); 
    } 
    catch { } 
    finally 
    { 
     if (s != null) s.Dispose(); 
    } 
} 
Console.WriteLine(DateTime.Now.Subtract(start) + " seconds"); 
+2

Điểm chuẩn có một số vấn đề. Điều quan trọng nhất là: Sử dụng 'Đồng hồ bấm giờ 'để đo và không phải' DateTime.Now'. 'Đồng hồ bấm giờ 'sử dụng bộ đếm hiệu suất và cung cấp cho bạn độ chính xác cao hơn. Sau đó, chạy mã mà không đo trước, có thể có một số thời gian khởi động mà mẫu của bạn đo được. –

+1

Trong thực tế, bạn sẽ nhận được kết quả ngược lại nếu bạn đặt try/finally for-loop đầu tiên trong mã của bạn và sau đó đo vòng lặp sử dụng. –

Các vấn đề liên quan