Skip to content

Performance of Dynamic Decorator

People seem interested in the Dynamic Decorator but concern about the performance overhead of the .NET remoting. Here, I try to clarify some mystery of the implementation of Dynamic Decorator.
 
First, the Dynamic Decorator does not use the runtime implementation of RealProxy. Instead, it implements its own RealProxy – ObjectProxy. Therefore, the performance overhead related to the runtime implementation of RealProxy does not apply to the ObjectProxy.
 
Second, let’s dig into the code of the ObjectProxy to see whether the performance is a concern. In Dynamic Decorator, a transparent proxy of the target object is returned by ObjectProxyFactory.CreateProxy method. The proxy is registered by the runtime so that when it is used to call a method, the runtime intercepts the call. This mechanism allows you to add preprocessing or postprocessing functionality before or after the target method invocation by overriding the Invoke method of the RealProxy.
 
If you step into the code, you will see the proxy call is resolved to a call of RealProxy.PrivateInvoke. The RealProxy.PrivateInvoke calls the virtual method RealProxy.Invoke, which is overridden by the ObjectProxy.
 
So, the actual work is done inside the overridden Invoke method. Inside the Invoke method of ObjectProxy, the preprocessing code is executed, then, the target method, finally, the postprocessing code.

public override IMessage Invoke(IMessage message)
{
    object returnValue = null;
    ReturnMessage returnMessage;

    IMethodCallMessage methodMessage = (IMethodCallMessage)message;
    MethodBase method = methodMessage.MethodBase;

    AspectContext aspCtx = new AspectContext(target, methodMessage);
    // Perform the preprocessing
    if (HasMethod(method.Name) && preAspect != null)
    {
        try
        {
            preAspect.Action(aspCtx, preAspect.Parameters);
        }
        catch (Exception e)
        {
            if (!preAspect.SuppressException)
            {
                returnMessage = new ReturnMessage(e, methodMessage);
                return returnMessage;
            }
        }
    }

    // Perform the call
    try
    {
        returnValue = method.Invoke(target, methodMessage.Args);
    }
    catch (Exception ex)
    {
        if (ex.InnerException != null)
            throw ex.InnerException;
        else
            throw ex;
    }

    // Perform the postprocessing
    if (HasMethod(method.Name) && postAspect != null)
    {
        try
        {
            postAspect.Action(aspCtx, postAspect.Parameters);
        }
        catch (Exception e)
        {
            if (!postAspect.SuppressException)
            {
                returnMessage = new ReturnMessage(e, methodMessage);
                return returnMessage;
            }
        }
    }

    // Create the return message (ReturnMessage)
    returnMessage = new ReturnMessage(returnValue, methodMessage.Args,
        methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
    return returnMessage;
}

People get impression that remoting is costly due to the runtime implementation of the RealProxy, or more specifically, the runtime implementation of Invoke method. However, that is not the case for ObjectProxy. As you see in the code of Invoke of ObjectProxy, there is no costly operations like crossing app domains, crossing contexts or context switch. It is simple code for preprocessing, target method invocation and postprocessing. They are all juicy stuff not overhead.
 
The other area of performance overhead is the intercept mechanism itself. It is a bit blackbox how the intercept mechanism is implemented. However, the logic behind is straightforward: if it is a transparent proxy object, call the Invoke method of its RealProxy. I cannot think of any costly operations in this.
 
In the end, the implementation of the Dynamic Decorator is very light and thin.

Advertisements

Hello world!

Welcome to WordPress.com. After you read this, you should delete and write your own post, with a new title above. Or hit Add New on the left (of the admin dashboard) to start a fresh post.

Here are some suggestions for your first post.

  1. You can find new ideas for what to blog about by reading the Daily Post.
  2. Add PressThis to your browser. It creates a new blog post for you about any interesting  page you read on the web.
  3. Make some changes to this page, and then hit preview on the right. You can alway preview any post or edit you before you share it to the world.