开发者

Improving performance of Castle's DynamicProxy?

开发者 https://www.devze.com 2023-01-25 00:20 出处:网络
I\'m currently trying to implement an AOP system to add automatic audits to decorated attributes of objects (done by an extended version of INotifyPropertyChanged). The automatic audit contains the pr

I'm currently trying to implement an AOP system to add automatic audits to decorated attributes of objects (done by an extended version of INotifyPropertyChanged). The automatic audit contains the propertyName it's old value and the new value.

I'm currently using Castle's DynamicProxy2 as there are excellent tutorials (namely this one:: http://kozmic.pl/archive/2009/04/27/castle-dynamic-proxy-tutorial.aspx) on how to use the tool. I generate a delegate for each property that is decorated for the type. The expression tree generates something like this:: (note I figure this is easier than pasting my expression tree code as my code relies on a type-safe reflection library and lots of static variables)

.Lambda #Lambda1<System.Action`1[Castle.DynamicProxy.IInvocation]>(Castle.DynamicProxy.IInvocation $invocation) {
    .Block(
        DutchTest.MixinTest $target,
        System.Object $argument,
        System.DateTime $newValue,
        System.DateTime $oldValue) {
        $target = (DutchTest.MixinTest).Call $invocation.get_InvocationTarget();
        $newValue = .Unbox($argument = .Call $invocation.GetArgumentValue(.Default(System.Int32)));
        .If (
            .Call (.Call System.Collections.Generic.EqualityComparer`1[System.DateTime].get_Default()).Equals(
                $oldValue = .Call $target.get_Created(),
                $newValue)
        ) {
            .Default(System.Void)
        } .Else {
            .Block() {
                .Call $invocation.Proceed();
                .Call ($target .As Dutch.Auditing.INotifyAuditedChange).OnPropertyChanged(.New Dutch.Auditing.AuditEventArgs(
                        "Created",
                        (System.Object)$oldValue,
                        $argument))
            }
        }
    }
}

I then have a custom selector which choses the DelegatedInterceptor (a class that implements IInterceptor, whose Intercept method is just to invoke the delegate. I also have a custom hook that only chooses the the p开发者_运维问答roperties that I plan on delegating (so I avoid the cost of proxying the get method).

Unfortunately, even with all these precautions I am looking at a substantial performance hit on every property set (it takes approximately .4 ticks to do that logic by hand and about 2.2 ticks if I do it with dynamic proxy, 2.8 ticks if I have to mixin the logic for INotifyAuditedChange and an event would be raised). This wouldn't be so bad, but as part of my requirements I am looking at very large amount of objects being modified.

Unfortunately, my plans to use typebuilder failed (it is way too hard to write the code with Reflection.Emit and apparently CompileToMethod cannot be used for instance methods), is there some tricks I am missing to improve the performance of DynamicProxy2?

0

精彩评论

暂无评论...
验证码 换一张
取 消