2010-09-02 9 views
6

Ceci est une question de suivi à thisCe qui est plus rapide - un bloc en utilisant ou try/catch/finally

Dois-je rester avec Try/Catch/Enfin construire, ou rendez-vous à l'aide de construire?

Exemple de code pour Try/catch/finally:

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 

Je sais ce que le code devrait être pour l'utilisation de la construction. Je veux juste savoir si l'utilisation de la construction d'utilisation serait plus rapide en comparant les cycles d'horloge.

+11

La balise 'using' beaucoup plus rapide . M'a sauvé environ 5 secondes de taper. – tidwall

Répondre

9

Il n'y aura pas de différence de performance. using est étendu par le compilateur à un bloc try/finally.

Vous verrez que les deux méthodes suivantes sont compilées en IL identique.

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(); 
    } 
} 

L'IL généré dans le premier cas est la suivante:

 
.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 

Dans le second cas, avec un try/finally en C#, nous obtenons:

 
.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

Vous manquez la prise là-bas. – tidwall

+0

@jojaba: Eh bien, j'ai décidé d'aller sans attraper dans l'exemple pour la simplicité. Si vous attendez que le corps de l'instruction using soit lancé, vous pouvez ajouter un try/catch. Mais notez que pour une comparaison équitable, vous devez ajouter la capture aux deux méthodes, c'est-à-dire ajouter une capture à la version try/finally * et * ajouter un bloc try/catch à l'intérieur ou à l'extérieur de l'instruction using. –

0

Je dois croire que l'utilisation de try/catch ne fera aucune différence en termes de performances par rapport au code que vous utilisez dans ces constructions.

2

using compile en try/catch/finally. Je ne vois vraiment pas de différence sémantique ou de performance, tant que vous disposez correctement de votre objet dans le cas d'un manuel try/catch.

Dans tous les cas, rendez-vous avec using, car il nettoie automatiquement (en fait dans la clause finally) pour vous. Même s'il y a une différence de performance, il est probablement si minime que vous avez de meilleurs endroits à optimiser.

0

Essayez/Catch/Enfin c'est plus rapide.

1) 6,638 sec: en utilisant tag
2) 6,265 sec: try/catch/finally

J'ai couru ce une douzaine de fois. Try/Catch/Enfin est toujours sorti en tête.

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

L'indice de référence a quelques problèmes. Les plus importants sont: Utilisez un 'Chronomètre' pour mesurer et non' DateTime.Now'. 'Stopwatch' utilise un compteur de performance et vous donne une plus grande précision. Ensuite, exécutez le code sans mesurer d'abord, il pourrait y avoir un temps de préchauffage que votre échantillon a mesuré. –

+1

En fait, vous obtiendrez le résultat opposé si vous placez d'abord la boucle try/finally dans votre code, puis mesurez la boucle using. –