Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiled Expressions #3

Merged
merged 3 commits into from Apr 30, 2013
Merged

Conversation

smithc
Copy link
Contributor

@smithc smithc commented Apr 29, 2013

Hi Mike,

I have been experimenting with using compiled expressions as a nice alternative to dynamic IL in order to increase performance of reflection-based APIs at runtime.

To that end, I have integrated the compiled expression equivalents of PropertyInfo's GetValue and SetValue. I have tried to minimize the amount of changes necessary to get this to work, but I did have to change a fair number of unit tests to get them passing with the new functionality. The SiteCore integration tests remain untested however.

If you think that these changes are OK as is, great! However, I also completely understand if you think this needs some reworking. The additional functionality is mostly self contained, so please feel free to re-work the integration aspect as you feel is necessary.

Please let me know if you have any questions, or if there is anything I can do to help.

Thanks,
Chris

@mikeedwards83
Copy link
Owner

This looks interesting, do you know how much quicker this code is than the original?

Cheers

Mike

@smithc
Copy link
Contributor Author

smithc commented Apr 29, 2013

The expression-based code executes approximately 10x faster on my machine than their reflection-based counterparts. Naturally, real performance metrics vary case by case, but the end result is that these should operate an order of magnitude faster.

As for real-world performance, I think on small sites these improvements will be negligible. We may potentially see milliseconds shaved off on sites with many objects and properties being bound per request though.

A quick search shows that somebody else has performed these benchmarks too, and they seem to agree with my own testing: http://www.palmmedia.de/Blog/2012/2/4/reflection-vs-compiled-expressions-vs-delegates-performance-comparision

Here's the code I used myself to test this. The PropertyUtil class simply contains the property getter/setter code:

class Program
{
    static void Main()
    {
        TimeSpan reflectionTime;
        TimeSpan expressionTime;
        double ratio = 0.0;

        const int numberOfIterations = 10000000;

        var stub = new Stub();

        PropertyInfo pi = stub.GetType().GetProperty("Prop");
        pi.GetValue(stub, null);
        pi.SetValue(stub, "hi", null);

        var getter = PropertyUtil.GetPropertyFunc<string>(stub.GetType(), "Prop");
        var setter = PropertyUtil.SetPropertyAction(stub.GetType(), "Prop");

        var sw = new Stopwatch();
        sw.Start();

        Console.WriteLine("\nBeginning Reflection Based Benchmark:");

        string value = string.Empty;

        for (int i = 0; i < numberOfIterations; i++)
        {
            value = (string) pi.GetValue(stub, null);
            pi.SetValue(stub, value, null);
        }

        sw.Stop();
        reflectionTime = sw.Elapsed;
        Console.WriteLine("Elapsed time: {0}", reflectionTime);
        Console.WriteLine("\nBeginning Compiled-Expression Based Benchmark:");
        sw.Restart();

        for (int i = 0; i < numberOfIterations; i++)
        {
            value = getter(stub);
            setter(stub, value);
        }

        sw.Stop();
        expressionTime = sw.Elapsed;
        Console.WriteLine("Elapsed time: {0}", expressionTime);

        ratio = reflectionTime.TotalMilliseconds / expressionTime.TotalMilliseconds;

        Console.WriteLine("\nRatio: {0}", ratio);
    }
}

class Stub
{
    public string Prop { get; set; }
}

@mikeedwards83
Copy link
Owner

I will have a go at merging this into a branch tonight and see how it performs. I have a couple of tests designed for testing the general performance of the Framework.

@mikeedwards83
Copy link
Owner

A quick test with a large number of properties (20) definitely shows a good performance improvement.

@mikeedwards83
Copy link
Owner

@TomDudfield I have merged this pull into branch pull3 (https://github.com/mikeedwards83/Glass.Mapper/tree/feature/pull3) and fixed the integration tests that broken in Sitecore. Could you take a look at the integration tests for Umbraco?

@mikeedwards83
Copy link
Owner

I just ran the integration tests for Umbraco and they have all passed. I will pull this into the development branch now.

@mikeedwards83 mikeedwards83 merged commit 7ad5a24 into mikeedwards83:develop Apr 30, 2013
@mikeedwards83
Copy link
Owner

I found one issue after the merge to dev detailed in Issue 4

mikeedwards83 pushed a commit that referenced this pull request Jul 16, 2015
bplasmeijer pushed a commit to valtech-nl/Glass.Mapper that referenced this pull request May 22, 2017
Revert of changes by Ralf in commit a603537...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants