Explore the creation of. Net objects and question the comparison between the performance of activator. createinstance (type) method for object creation and expression tree object Creation

Source: Internet
Author: User
Tags reflector
Today, Will Meng published an article titled "talking about activator. the createinstance (type) method creates an object and the Expression Tree creates an object performance comparison. This article passes a series of comparative tests and draws a conclusion: "The result method is activator. createinstance () is faster than the expression tree."
However, in my personal use, I had a question about this result. I took some time to perform a more detailed test based on my principle, the test mainly targets the following methods for constructing objects:
1. Direct Initialization
2. Construct the delegate through the expressiontree to initialize
3. Use emit to construct delegation Initialization
4. Call activator. createinstanse (type) to initialize
5. Call activator. createinstanse <t> () to initialize
6. Use traditional reflection for initialization
During the test, use Lao Zhao's codetimer timing to test Code As follows: Code

Type type =   Typeof (Testclass );
Func < Testclass > Fun = Getcreatefunc ();
Fun ();
Func < Testclass > Fun2 = Getemitcreatefunc ();
Fun2 ();
Activator. createinstance (type );
Activator. createinstance < Testclass > ();
VaR method = Type. getconstructors ()[ 0 ];
Method. Invoke ( Null );
Getcache. instancecacheex. instancecache (type );
Int Num =   1000000 ;
Codetimer. initialize ();
Codetimer. Time ( " Newinstanse " , Num ,() => {
New Testclass ();
});
Codetimer. Time ( " Expressioncreate " , Num ,() => {
Fun ();
});
Codetimer. Time ( " Emitcreate " , Num ,() => {
Fun2 ();
});
Codetimer. Time ( " Activatorcreate " , Num ,() => {
Activator. createinstance (type );
});
Codetimer. Time ( " Reflectioncreate " , Num ,() => {
Method. Invoke ( Null );
});
Codetimer. Time ( " Genericcreate " , Num ,() => {
Activator. createinstance < Testclass > ();
});

The test process is to construct simple objects. The test results are shown in:

Check the test results. Obviously, the results are different from those of Will Meng. in the above test results, direct Initialization is the fastest. The expressiontree and edmit initialization speed are basically the same, which is a little slower than direct initialization, followed by activator. the createinstanse method surprised the activator. the createinstanse <t> method is the slowest. therefore, two questions are raised:
1. Why are there so many differences between this test result and will Meng?
2. Why is activator. createinstanse <t> slower than traditional reflection?
First, let's look at the first question. Right, we get the final result. First, we will reproduce the testing environment of Will Meng and put this part of code into my testing project, however, there is a small problem in the reproduction process.

I have made some simple changes to this line that cannot be compiled. then the test was conducted. I put the Code Constructed by Will Meng into codetimer for testing, copied the code, and tested the code. The test result is shown in figure (due to the limited screen height, this image is divided into two parts ):


The results of codetimer show that the Code on the expressiontree constructed by Will men is still very efficient, but it is still much slower than the direct delegate execution. I personally think the reason is the redundant code, such as the dictionary, method calls consume a lot of time. however, in my system, the same test code as will men also shows different test results. In my test environment, expression. createinstanseex is better than activator. createinstanse consumes more than 2/3 less time. therefore, I am very confused about the test of Will men. I also hope that some friends can help me solve the same code and the test results differ so much.
At this point, the first problem is basically solved. In my personal test environment, the efficiency of constructing objects in the expressiontree is obviously much higher than that in activator. createinstanse.
The second problem is solved below. Why is activator. createinstanse <t> is more powerful than activator. createinstanse is so slow that it is even slower than direct reflection. To solve this problem, we have to ask the reflector tool to view the specific implementation of the two methods. We may take it for granted that activator. createinstanse <t> is to call activator. the createinstanse method then converts the object to T, but the result of reflector viewing is not so. Microsoft implements the two methods completely differently. Let's take a look at activator. implementation of createinstanse <t>:

We can see that this method finally calls runtimetypehandle. the createinstance method is used to construct the object and return the result. Next let's take a look at activator. implementation of createinstanse, activator. createinstanse (type) indirectly calls activator. createinstanse (type, bool nonpublic). Therefore, we can directly view the implementation of this method:

Obviously, the two methods adopt different methods. This method finally calls underlyingsystemtype. createinstanceimpl to construct the object. To get the final answer, we will continue to check the implementation of underlyingsystemtype. createinstanceimpl method:

It is still a transit call. Continue to view:

Finally, we can see the key implementation. Here, this method uses activatorcache for caching. When no cache is available, createinstanceslow is called. Let's continue to check the implementation of createinstanceslow:

Here we see the familiar runtimetypehandle. createinstance to construct an Uncached object. Obviously, Microsoft also knows runtimetypehandle. createinstance is not efficient, so activator. the createinstanse method uses cache to improve efficiency, but it is strange that activator. the createinstanse <t> method bypasses the cache and directly calls the inefficient method, which is confusing.
Now, we have opened two questions raised at the beginning. In this article, we can draw a conclusion that in object construction, we should first adopt direct construction, in some environments that require dynamic creation, use the expressiontree or emit method as much as possible. If this part cannot meet the requirements, you can consider using a less efficient activator. the createinstanse method, and lower-efficiency reflection calls are generally not included in our consideration. The most important thing is that, in general, activator is not used as much as possible, especially for efficiency requirements. createinstanse <t> method.

 

Supplement:

Seeing the poor design of activator. createinstanse <t>, some friends directly questioned that it should be a temporary worker. Therefore, I checked the implementation of this method in. net4.0 beta2, for example:

Continue viewing createinstansedefaultctor

It seems that this issue has been fixed in the new framework.

Related Article

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.