J'ai réfléchi à des instructions try/catch imbriquées et j'ai commencé à réfléchir aux conditions, le cas échéant, dans lesquelles le JIT peut effectuer une optimisation ou une simplification de l'IL compilé. Pour illustrer, considérons les représentations fonctionnellement équivalentes suivantes d'un gestionnaire d'exceptions.Le .NET JIT optimise-t-il les instructions try/catch imbriquées?
// Nested try/catch
try
{
try
{
try
{
foo();
}
catch(ExceptionTypeA) { }
}
catch(ExceptionTypeB) { }
}
catch(ExceptionTypeC) { }
// Linear try/catch
try
{
foo();
}
catch(ExceptionTypeA) { }
catch(ExceptionTypeB) { }
catch(ExceptionTypeC) { }
Si l'on suppose qu'il n'y a pas de références variables supplémentaires ou des appels de fonctions dans les cadres de pile de l'instruction try imbriqué, peut le JIT conclure que les cadres de pile peuvent être réduits à l'exemple linéaire?
Maintenant, que diriez-vous de l'exemple suivant?
void Try<TException>(Action action)
{
try
{
action();
}
catch (TException) { }
}
void Main()
{
Try<ExceptionC>(Try<ExceptionB>(Try<ExceptionA>(foo)));
}
Je ne pense pas qu'il y ait aucune façon pour le JIT inline les invocations des délégués, donc cet exemple ne peut pas être réduit à la précédente. Cependant, dans le cas de foo()
en lançant ExceptionC
, cette solution est-elle moins performante que l'exemple linéaire? Je soupçonne qu'il y a un coût supplémentaire pour démolir les cadres de pile à partir des invocations de délégué, même si les données supplémentaires contenues dans les cadres sont minimes.
Avez-vous regardé l'IL pour les deux premiers cas? – womp