MarcinJuraszek / CloneExtensions

Clone extension method library. Performs fast, deep or shallow clone using simple assignment operations generated by Expression Tree runtime code compilation.
Apache License 2.0
115 stars 30 forks source link

Leverage backing fields for automatic properties (speed tweak). #22

Closed deipax closed 7 years ago

deipax commented 7 years ago

In other work I have done with reflection in setting fields and properties on classes and structs, it came to my notice that fields were faster than properties. After looking into the issue, other people noted the same behavior and confirmed that properties do indeed have overhead associated with them. With a little more research, I discovered that automatic properties use fields (backing fields) under the hood and that with a little work those fields can be used to set/get the underlying value instead of the property if they exist ... allowing the user to forgo the overhead associated with properties. For other properties that implement a set/get, non-automatic properties, the Property is and must be used instead.

I have added a class, ModelInfo, from my personal library that I use to accomplish the task at hand. In addition to ModelInfo, I also added some interfaces, extension methods and the unit tests to assert behavior of the ModelInfo class. Here are some pre and post performance changes that are effected by this change (all values in operations per second):

A Complex Class: 1,701,644 -> 3,640,776 (about a 114% increase, 2.14 times faster) A Simple Class: 2,121,640 -> 6,607,929 (about a 211% increase, about 3.11 times faster) Array of Classes: 24,009 -> 66,006 (about a 175% increase, 2.75 times faster) Array of Structs: 28,876 -> 149,812 (about a 419% increase, 5.19 times faster)

For a more complete comparison, you can view the attached files. If you have any questions, please feel free to ask.

-Jeff

Pre.txt Post.txt

Note: All the added code is original, from my efforts alone.

deipax commented 7 years ago

Marcin, If you are interested, I uploaded my personal project under my profile which contains the work I did based of your code among other things. In it, you will find the unit tests that I run to generate the performance files I attached above.

-Jeff

deipax commented 7 years ago

Marcin, Have you had a chance to review this change set? Once it is done, I would like to discuss support for polymorphism ... the performance hit is only about 10 to 15%, which has been easily made up from all the previous efficiency changes.

-Jeff

MarcinJuraszek commented 7 years ago

I created https://github.com/MarcinJuraszek/CloneExtensions/pull/24 with a simplified version of your optimization - it does not use any additional caching, which I think in this particular scenario is not necessary (and benchmarks seem to confirm that). Could you take a look and see if I'm not missing anything?

MarcinJuraszek commented 7 years ago

I'm closing this one in favor of a simpler solution in https://github.com/MarcinJuraszek/CloneExtensions/pull/24 which does not introduce extra caching layer. Let me know if you disagree.