Read Catalogue
- Begin
- Disadvantages of using delegate to optimize reflection
- Advantages of using delegate to optimize reflection
- Advantages of using CodeDom to optimize reflection
- How to use the CodeDom well?
- Disadvantages of using CodeDom to optimize reflection
- Can I not use a delegate?
- Select an optimization method based on the degree of reflection density
- The mistaken idea of CodeDom optimization
- Summary of Reflection Optimization
In the first two blogs, I introduced two ways to optimize reflection:
1. Delegate: Delegate.
2. CodeDOM: Dynamic code generation.
There are two different ways to do this, and the difference in performance is great.
Today's blogs will focus on comparing their pros and cons, as well as giving suggestions for their use.
Back to top use delegate to optimize reflection disadvantage
In evaluating the delegation proposal, I think it is necessary to subdivide the delegation scheme:
1. Strongly typed delegates, for example: Action<ttarget, tvalue>
2. Weakly typed delegates, for example: Action<object, object>
Their advantages are:
strongly typed delegate: fast, already closest to the performance of direct invocation, however its disadvantage is not universal.
Weakly typed delegates: relatively generic, and after some code encapsulation, easy to use, but the performance of the package will become worse.
Back to top using delegate to optimize the reflection advantage
There are two advantages:
1. easy to implement , whether using emit, expressiontree or createdelegate, the amount of code is small.
2. The method is generic , using weakly typed delegates, we can encapsulate an easy-to-use API and apply to any project.
Back to top the advantages of using CodeDom to optimize reflection
The biggest, but also the only advantage is: good performance.
There is no performance loss because the code that is called directly is generated, so the code that runs the call is eventually run.
In addition, the code generator can determine the resulting code quality, the better the code generator, the better the performance of the code.
Note: When using this technique, different people may have different ways of using it, and eventually can get different performance results, and (theoretically) the worst case may be worse than the delegate.
If you want to achieve the best performance with this optimization, there are two things to do:
1. Ensure that the resulting code quality is optimal.
2. The design of the compiling method should be reasonable (with good CodeDom).
How to ensure that the final generated code quality is optimal, I can not give advice, need you to think,
We proceed to the 2nd.
Back to the top how to use the CodeDom well?
While dynamic compilation techniques are used, we can generate directly called code instead of reflection calls, so there is no performance penalty.
However, there is one more question to consider: What granularity do I have to generate code?
1. Is the code generated for each reflection call?
2. Or do you batch generate a piece of code for each type?
3. Do you still generate a batch of code for a bunch of types in large quantities?
Because the results of dynamic compilation cannot be called directly, we can only invoke it by means of a delegate or an interface.
So if the granularity of each code generation is small, it will produce a lot of assemblies and will consume more compiler startup time.
Therefore, this is not an efficient approach. The efficient approach should be to generate as much code as possible at once.
In addition, there is one more question to consider: What to do when you need to loop through the compilation results?
For such scenarios, I recommend that the loop process be generated directly when the code is generated, and that the entire invocation process is completed by invoking the compilation results only once.
For example, we can generate similar code for the data access layer, including loops, creating entity objects, and all operations that assign values to attributes:
public static list<product> loadproduct (DbDataReader reader) { list<product> List = new List<product > (); while (reader. Read ()) { Product P = new Product (); P.productid = (int) reader["ProductID"]; P.productname = reader["ProductName"]. ToString (); P.categoryid = (int) reader["CategoryID"]; P.unit = reader["Unit"]. ToString (); P.unitprice = (decimal) reader["UnitPrice"]; P.remark = reader["Remark"]. ToString (); p.quantity = (int) reader["Quantity"]; List. ADD (P); } return list;}
If we generate such code, and then we only need one call at a time, we can replace the previous hundreds of delegate calls and cache lookups, and the lock conflicts will be minimized.
Back to top the disadvantage of optimizing reflection with CodeDom
There are three disadvantages:
1. methods are not generic and need to generate different direct calling code for different types and different data sources, so it is difficult to generalize.
2. The complexity is high , because it is the code that generates the direct call, and the data type and format is unknown, so it is necessary to carefully consider various situations and increase complexity.
3. difficult to encapsulate , because the result of the compilation is an assembly, it can not be called directly, but also need to use other means to invoke, it is difficult to achieve a more general encapsulation.
Back to the top can you not use the delegate?
Since we can generate code dynamically and compile them at run time to replace the target of reflection, we do not need the optimization method of the delegate invocation.
So, does it make sense to delegate? Or can you not use delegates when optimizing reflection?
In the previous blog, I demonstrated the method of dynamic compilation.
Because the result of a dynamic compilation is an assembly, it cannot be called directly, and we need to use other methods to invoke it.
The blog introduces two methods, one of which is to use delegates to invoke the methods in the assembly.
Since the code generated at runtime is generated by our code, the signature of the method can be controlled,
So, when you call the Delegate.createdelegate method, you don't get into any trouble,
Therefore, it is convenient to invoke the results of the CodeDom compilation by a strongly typed delegate.
It is for this reason that when you choose to generate a method of the static type, the delegate is still required, at which point the delegate and the CodeDom will be a coexistence relationship.
If you use the design of the interface when generating the code, then the delegate is not necessary.
Back to top Select an optimization method based on the degree of reflection density
Is it best to select the CodeDom, or choose delegate, to optimize the reflection?
I think we should separate the discussion according to the intensity of the reflection.
1. Low Reflection density : For example: An HTTP request process, our code only needs one or two reflection operations,
Or, for desktop applications, several reflection calls are used in response to user click events.
In such a scenario, the intensity of the reflection is considered to be very low. So how do we optimize this situation?
My answer is: optimization does not matter, because the reflection is not too slow to accept.
How slow is the speed of reflection? Let's take a look at the tests we've done before:
From this image (from the first part of this series) it can be seen that the property assignment operation is performed in a reflection manner, even if it runs 1 million times, it only takes 1.2 seconds! To know that my test machine was bought 3 years ago laptop, if replaced by the current professional server, consumes less time, therefore, this kind of reflection optimization value is small. Of course, it's not a bad thing if you're willing to optimize them.
2. high degree of reflection density : For example, in the application of the data access layer, when an entity list is loaded at a time, the number of reflections is multiplied by the number of fields, plus the number of entity objects created. This number can easily reach hundreds of levels, and during an HTTP request, you may need to load a variety of data, so the number of reflections is considerable. We often feel that the execution of various serialization and deserialization programs is inefficient, which is directly related to reflection. However, we do not usually need to write serialization deserialization programs, and we can only be forced to accept their performance. Therefore, for highly reflective code, if the optimization method is not ideal, it will certainly affect performance.
3. The degree of concentration between the two before. Because such scenarios are not qualitatively measurable, and different people are sensitive to performance, or because different applications have different performance requirements.
Thus, the scope of such a scenario can only be evaluated on its own, and the optimization method can only be selected by itself:
1. If you are concerned about performance, choose CodeDom,
2. Otherwise choose delegate Bar, after all, this method is simple to use.
Go back to the top of the CodeDom optimization error
1. Does CodeDom really increase the performance of the program by a few thousand?
According to the previous, we know that the performance of direct call than reflection call to increase thousands of thousand, so it is not possible to consider the use of dynamic compilation method, the performance of the program can be increased thousands of thousand?
The answer is in the negative. For example, taking a scene that creates an entity object, although the reflection call takes time and the direct call times out, even though we use dynamic compilation instead of reflection, we need to get the data for those properties before assigning a value to the attribute. However, the operation to get data is likely to be slower than reflection, so we can optimize only a small part of the process so that when we test the entire process, performance does not rise to thousands of thousand. How much performance is increased depends on the proportion of time it takes to reflect the entire process.
2. The CodeDom scheme must be faster than the delegate scheme.
The answer is no, as explained earlier, if you generate a method for each reflection call (the idea of a delegate), then you still need a delegate or an interface to invoke, and at this point the compiler start time, the final performance will be slower than the delegate.
Back to top Reflection optimization summary
The fundamental method of reflection optimization is only one way: avoid reflection.
However, the method of avoidance can be divided into two types:
1. Use the delegate to invoke. Mealy
2. Generate the direct calling code, instead of the reflection call. Straightforward
There are pros and cons to all two of these methods, and I think the choice of which method should be based on the reflection scenario:
1. The invocation target is explicit (both the name and the type are known): The strongly typed delegate method is a good choice.
2. The invocation target is ambiguous and the call is intensive: The dynamic compilation method is the best choice.
3. Other situations: You can delegate with weak types, or do not optimize.
The Reflection Performance optimization of C # 3