Many posts have analyzed the Try-Catch mechanism and its impact on performance.
However, there is no evidence that Try-Catch consumes too much of the system's performance, especially in a hosted environment. I remember a netizen in the garden analyzed Try-Catch using StopWatch. In different cases, the results of code running time indicators are not very different from those without Try-Catch.
Next I will analyze Try-Catch in combination with IL.
● Mechanism Analysis
In. Net, the basic exception capture and handling mechanism is by try... Catch... Finally blocks are used to monitor, capture, and handle exceptions. A try block can correspond to zero or multiple catch blocks, and can correspond to zero or one finally block. However, try without catch does not seem meaningless. If try corresponds to multiple catch, the CLR will search for the catch Block Code from top to bottom after an exception is detected, filter the corresponding exceptions using the exception filter. If no exception is found, the CLR searches for an exception from the higher level along the call stack. If no exception is found at the top of the stack, an unhandled exception will be thrown, and the code in the catch block will not be executed. So the catch Block closest to try will be first traversed.
The following code is available:
Try
{
Convert. ToInt32 ("Try ");
}
Catch (FormatException ex1)
{
String CatchFormatException = "CatchFormatException ";
}
Catch (NullReferenceException ex2)
{
String CatchNullReferenceException = "CatchNullReferenceException ";
}
Finally
{
String Finally = "Finally ";
}
The corresponding IL is as follows:
. Method private hidebysig instance void Form1_Load (object sender,
Class [mscorlib] System. EventArgs e) cel managed
{
// Code size 53 (0x35)
. Maxstack 1
. Locals init ([0] class [mscorlib] System. FormatException ex1,
[1] string CatchFormatException,
[2] class [mscorlib] System. NullReferenceException ex2,
[3] string CatchNullReferenceException,
[4] string Finally)
IL_0000: nop
IL_0001: nop
IL_0002: ldstr "Try"
IL_0007: call int32 [mscorlib] System. Convert: ToInt32 (string)
IL_000c: pop
IL_000d: nop
IL_000e: leave. s IL_0026
IL_0010: stloc.0
IL_0011: nop
IL_0012: ldstr "CatchFormatException"
IL_0017: stloc.1
IL_0018: nop
IL_0019: leave. s IL_0026
IL_001b: stloc.2
IL_001c: nop
IL_001d: ldstr "CatchNullReferenceException"
IL_0022: stloc.3
IL_0023: nop
IL_0024: leave. s IL_0026
IL_0026: nop
IL_0027: leave. s IL_0033
IL_0029: nop
IL_002a: ldstr "Finally"
IL_002f: stloc. s Finally
IL_0031: nop
IL_0032: endfinally
IL_0033: nop
IL_0034: ret
IL_0035:
// Exception count 3
. Try IL_0001 to IL_0010 catch [mscorlib] System. FormatException handler IL_0010 to IL_001b
. Try IL_0001 to IL_0010 catch [mscorlib] System. NullReferenceException handler IL_001b to IL_0026
. Try IL_0001 to IL_0029 finally handler IL_0029 to IL_0033
} // End of method Form1: Form1_Load
Several lines of code at the end reveal how IL handles exceptions. Each Item in the last three rows is called Exception Handing Clause, and EHC forms an Exception Handing Table. EHT is separated from normal code by the ret return command.
As you can see,FormatExceptionIn the first place of EHT.
When the code is successfully executed or otherwise returned, the CLR will traverse the EHT:
1. if an exception is thrown, CLR will find the corresponding EHC (IL_0001 to IL_0010In this example, the CLR finds two EHC records,FormatExceptionIt is first traversed and suitable for EHC.
2. If the Returned Code address isIL_0001 to IL_0029, Then the executionFinally handlerThat isIL_0029 to IL_0033Code in, whether or not it is returned for successful Code Execution.
In fact, the catch and finally traversal work are carried out separately. As mentioned above, the CLR first implements traversal catch. When a suitable catch Block is found, it then traverses the corresponding finally; in addition, this process will be performed recursively at least twice, because the compiler will... Catch... Finally is translated into two layers of nesting in IL.
Of course, if the corresponding catch block is not found, the CLR will execute finally directly and immediately Interrupt all threads. The code in the Finally block is certainly executed, regardless of whether the try detects exceptions.
● Suggestions for improvement
From the preceding content, we can conclude that:
If "Try-Catch" is used and an exception is caught, the CLR only performs traversal.Exception Handing Table.TraversalThe Finally item in the Exception Handing Table takes almost all the time to traverse the Exception Handing Table. If no Exception is caught, the CLR just traverses the Finally item in the Exception Handing Table, which takes little time.
The time used to execute the corresponding operation after "Try-Catch" traversal is determined according to your code. "Try-Catch" only causes monitoring and triggering, this part of code time should not be counted as the consumption of "Try-Catch.
Therefore, you can consider performance and code review. The following guidelines are generally recommended:
1. Try to give the CLR a clear Exception information. Do not use Exception to filter exceptions.
2. try not to try... Catch is written in a loop
3. try as few code as possible. If necessary, you can use multiple catch blocks and write the exception type most likely to be thrown to the nearest position of try.
4. Do not declare only one Exception object, rather than process it. In this case, the length of the Exception Handing Table is added in vain.
5. Use the "CLR Exceptions" of the performance counter utility to detect Exceptions and optimize them as appropriate
6. Use the Try-Parse mode of the member. If an exception is thrown, use false to replace it.
Conclusion: Although Try-Catch consumes a little time, programmers do not have to talk about it. Through the above analysis, it is not so much that "Try-Catch" will consume or affect performance, it is better to say that "Try-Catch" is the same as other code, but it is only a common consumer of performance. To consider code writing review, Try to take care of "Try-Catch.