Summary of optimization of reflection performance (II)

Source: Internet
Author: User

In the first two blogs, I introduced two methods to optimize reflection:
1. Delegate: Delegate.
2. CodeDOM: dynamic code generation.
This is two completely different methods, and the performance gap is also large.
Today's blog will focus on comparing their advantages and disadvantages and providing their usage suggestions.

Disadvantages of using Delegate to optimize reflection

When evaluating the delegated scheme, I think it is necessary to subscribe to the delegated scheme:
1. Strongly typed delegation, for example, Action <TTarget, TValue>
2. Weak type delegation, such as Action <object, object>

They have the following advantages:
Strongly-typed delegation:The speed is fast and the performance is closest to that of direct calls. However, its disadvantage is thatNot common.

Weak type delegation:It is more common and can be used easily after some code encapsulation,The encapsulated performance degrades.

Advantages of using Delegate to optimize reflection

There are two advantages:
1.Easy to implementWhether it is Emit, ExpressionTree, or CreateDelegate, the amount of code is not large.
2.Common MethodsWith weak type delegation, we can encapsulate APIs that are easy to use and apply to any project.

Advantages of using CodeDOM to optimize reflection

The biggest and only advantage is:Good performance.
Because the code is directly called, the code that is directly called is finally run, so there is no performance loss.
In addition, the Code generator can determine the final quality of the generated code. The better the code generator, the better the code performance.

Note: When this technology is used, different people may use different methods to get different performance results,
(Theoretically) the worst case may be worse than the Commission.

If you want to use this optimization method to achieve the best performance, you need to do two things:
1. Ensure that the final generated code quality is optimal.
2. The compilation method should be properly designed (CodeDOM should be used properly ).

How can we ensure that the final generated code quality is optimal? I can't provide suggestions, so you need to think about it yourself,
Next we will discuss the 2nd points.

How to Use CodeDOM well?

Although dynamic compilation technology is used, we can generate code for direct calls instead of reflection calls, so there will be no performance loss.
However, there is another question to consider: At what granularity should I generate code?
1. Is code generated for each reflection call?
2. still generate code for each type in batches?
3. Is it possible to generate a batch of code for a bunch of types in large batches?

Because the results of dynamic compilation cannot be called directly, we can only use the delegate or interface method to call them,
Therefore, if the granularity of each code generation is small, a large amount of assembly will be generated, and a large amount of compiler startup time will be consumed,
Therefore, this is not an efficient approach. An efficient approach should be to generate as much code as possible at a time.

In addition, there is another question to consider: What should we do when we need to call the compilation result cyclically?
For such scenarios, we recommend that you generate the loop process directly when generating code, and finally use only one call to compile the result to complete the entire call process.
For example, we can generate such code for the data access layer to include all the operations such as loops, object creation, and attribute assignment:

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, we only need to call it once at last, instead of the previous hundreds of delegate calls and cache searches, the lock conflicts will also be minimized.

Disadvantages of using CodeDOM to optimize reflection

There are three disadvantages:
1.Method not universalTo generate different direct call codes for different types and data sources, so it is difficult to generalize.
2.High complexityBecause the code for directly calling is generated and the data type and format are unknown, various situations need to be carefully considered and the complexity increases.
3.Difficult to encapsulateBecause the compilation result is an assembly, it cannot be called directly, but it also needs to be called in other ways, so it is difficult to implement a more general encapsulation.

Can I not use delegation?

Since we can dynamically generate code and compile them at runtime to replace reflection, we do not need to delegate the called optimization method.
Is delegation meaningful? Or can we ignore delegation when optimizing reflection?

In my previous blog, I demonstrated the dynamic compilation method.
Because the result of dynamic compilation is an assembly, it cannot be called directly. We need to use other methods to call it.
The blog introduced two methods, one of which is to call the methods in the Assembly by Delegate.
Because the code generated at runtime is generated by our code, we can control the method signature,
Therefore, you will not have any trouble calling the Delegate. CreateDelegate method,
Therefore, it is very convenient to call the CodeDOM compilation result through a strongly typed delegate.
For this reason, when you select to generate a static method, the delegate is required. At this time, the delegate and CodeDOM will coexist.

If you use the interface design scheme when generating code, you do not need to use the delegate.

Selection of Optimization Methods Based on reflection density

To optimize reflection, do you choose CodeDOM or Delegate?
I think we should discuss it separately based on different reflection density levels.

1.Low Reflection DensityFor example, during an HTTP request, our code only needs one or two reflection operations,
Or for a desktop program, several reflection calls are used in response to user click events.
In such scenarios, the intensity of reflection is considered very low. In this case, how should we optimize it?
My answer is:Optimization doesn't matter, because reflection is not too slow to accept.
How slow is the reflection speed? Let's take a look at the previous tests:

From this image (from the first article in this series), we can see that it takes only 1000000 seconds to perform the attribute assignment operation using reflection!
You know, my laptop was bought three years ago. If I switch to a professional server, it will consume less time,
Therefore, optimization of such reflection is of little value.
Of course, it is not a bad thing if you are willing to optimize them.

2.High Reflection DensityFor example, in an application at the data access layer,
When an object list is loaded at a time, the number of reflections is the number of pages multiplied by the number of fields, plus the number of object creation objects.
This number can easily reach hundreds of times, and multiple types of data may need to be loaded during an HTTP request, so the number of reflections is considerable.

We often feel that the execution efficiency of various serialization and deserialization programs is not high, which is directly related to reflection.
However, we usually do not need to write serialized deserialization programs, and we can only accept their performance.
Therefore, for code with high reflection density, if the optimization method is not ideal, performance will certainly be affected.

3. It is concentrated between the first two. This type of scenario cannot be measured in a qualitative way,
In addition, different people are not sensitive to performance, or because different applications have different performance requirements.
Therefore, the scope of such scenarios can only be evaluated by yourself, and the optimization method can only be selected by yourself:
1. If you are concerned about performance, select CodeDOM,
2. Otherwise, select Delegate. After all, this method is easy to use.

Misunderstanding of CodeDOM Optimization

1. Can CodeDOM improve the program performance by thousands of times?
According to the previous steps, we know that direct calling is times better than reflection calling,
Therefore, can I think that the performance of a program can be improved by thousands of times by using the dynamic compilation method?

The answer is no. For example, in the scenario of object creation, although the time difference between reflection calls and direct calls is several thousand times,
Even if we use dynamic compilation instead of reflection, we need to get data for those attributes before assigning values to the attributes.
However, data retrieval operations are likely to be slower than reflection operations. Therefore, we can optimize only a small part of the process,
Therefore, when we test the entire process, the performance will not be improved to a thousand times.
How many times of performance improvement depends on the percentage of time spent by reflection throughout the process.

2. The CodeDOM solution must be faster than the Delegate solution.

The answer is no. As mentioned above, if you generate a method (delegate idea) for each reflection call, you still need a delegate or an interface to call it,
In addition, the compiler startup time is added, and the final performance will be slower than that of the delegate.

Reflection optimization Summary

There is only one fundamental approach to reflection optimization: avoiding reflection.
However, there are two methods to avoid:
1. Use a delegate to call the API. (Detour)
2. generate direct call code to replace reflection call. (Straightforward)

Both methods have advantages and disadvantages. I think the method should be determined based on the reflection scenario:
1. The call target is clear (both the name and type are known): The strongly typed delegate method is a good choice.
2. Unclear call targets and intensive calls: dynamic compilation is the best choice.
3. Other cases: weak type delegation or not optimized.

Click here to download the sample code

If you believe that reading this blog has some benefits, click 【Recommendation] Button.
If you want to discover my new blog more easily, click 【Follow Fish Li].
Because my enthusiasm for writing is inseparable from your support.

Thank you for reading this article. If you are interested in the content of my blog, please continue to follow up on my blog. I am Fish Li.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.