Улучшение производительности Castle's DynamicProxy? - PullRequest
1 голос
/ 15 ноября 2010

В настоящее время я пытаюсь внедрить систему AOP для добавления автоматических аудитов к оформленным атрибутам объектов (выполняется расширенной версией INotifyPropertyChanged). Автоматический аудит содержит propertyName, его старое значение и новое значение.

В настоящее время я использую Castle's DynamicProxy2, так как есть отличные учебные пособия (а именно этот: http://kozmic.pl/archive/2009/04/27/castle-dynamic-proxy-tutorial.aspx) о том, как использовать инструмент. Я генерирую делегат для каждого свойства, которое оформлено для типа. Выражение tree генерирует что-то вроде этого: (обратите внимание, я полагаю, что это проще, чем вставлять мой код дерева выражений, так как мой код опирается на безопасную для типов библиотеку отражений и множество статических переменных)

.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))
            }
        }
    }
}

Затем у меня есть пользовательский селектор, который выбирает DelegatedInterceptor (класс, который реализует IInterceptor, чей метод Intercept предназначен только для вызова делегата. У меня также есть пользовательский хук, который выбирает только те свойства, которые я планирую делегировать ( поэтому я избегаю затрат на проксирование метода get).

К сожалению, даже со всеми этими мерами предосторожности я смотрю на существенное снижение производительности для каждого набора свойств (для выполнения этой логики вручную требуется около 0,4 тиков и около 2,2 тиков, если я делаю это с динамическим прокси, 2,8 тиков, если Я должен смешать логику для INotifyAuditedChange, и событие будет вызвано). Это не было бы так плохо, но в рамках моих требований я смотрю на очень большое количество изменяемых объектов.

К сожалению, мои планы по использованию typebuilder провалились (слишком сложно написать код с Reflection.Emit и, очевидно, CompileToMethod не может использоваться для методов экземпляра), есть ли какие-то хитрости, которые мне не хватает, чтобы улучшить производительность DynamicProxy2?

...