在C#上测量每种方法的编译时间

时间:2015-02-11 13:09:42

标签: c# performance interceptor

我们将创建一个性能对我们来说非常重要的Web服务。因此我们决定了每种方法的测量编译时间。

我们希望拦截每个方法并记录编译时间。但是我们不想更改发布的代码。因此,我们如何才能使这个拦截器仅在调试模式下运行?

1 个答案:

答案 0 :(得分:0)

这是拦截器,它计算一个类中的每个方法。 (它使用log4net)

internal class DurationCalculatorAspect : IMessageSink
{
   public bool ExceptionHandlingEnabled { get; set; }

    internal DurationCalculatorAspect(IMessageSink next,bool exceptionHandlingEnabled)
    {
        m_next = next;
        ExceptionHandlingEnabled = exceptionHandlingEnabled;
    }

    private IMessageSink m_next;
    #region IMessageSink implementation
    public IMessageSink NextSink
    {

        get { return m_next; }
    }

    public IMessage SyncProcessMessage(IMessage msg)
    {
        var typeResolver = ((System.Type[])(((System.Collections.ArrayList)msg.Properties.Values)[2]));
        var typeName = "void";
        if(typeResolver.Count()!=0)
        {
            typeName = typeResolver[0].FullName;
        }

        var argsString = "";
        var argArray =(object[])((System.Collections.ArrayList)msg.Properties.Values)[4];
        for (int i = 0;i<argArray.Length;i++)
        {
            argsString+=(i+1).ToString() + ". Object : " +argArray[i];
        }
        Logger.GetLogger().Debug("MethodName : "+((System.Collections.ArrayList)msg.Properties.Values)[1]+"\r\n"+
            "TypeName: " + typeName + "\r\n" + "Args : " + argsString
            );
        var date1 = DateTime.Now;


      var  returnMethod =
        m_next.SyncProcessMessage(msg);

        var returnMessage = ((IMethodReturnMessage)returnMethod);

        var date2 = DateTime.Now;
        Logger.GetLogger().Debug("MethodName : " + returnMessage.MethodName + "Duration : " + date2.Subtract(date1).TotalMilliseconds + " .ms"+"\r\n"+
            "TypeName: " + typeName + "\r\nReturned : " +returnMessage.ReturnValue);

        if (returnMessage.Exception != null)
        {
            Logger.GetLogger().Fatal("Exception : " + returnMessage.Exception.Data + " InnerException : " + returnMessage.Exception.InnerException);
            if (ExceptionHandlingEnabled)
            {
                return new ReturnMessage(null, null);
            }
        }


        return returnMethod;
    }

    public IMessageCtrl AsyncProcessMessage(IMessage msg,
    IMessageSink replySink)
    {
        throw new InvalidOperationException();
    }

    #endregion //IMessageSink implementation

}

public class DurationCalculatorInterceptorProperty : IContextProperty,
IContributeObjectSink
{
    public bool ExceptionHandlingEnabled { get; set; }

    public DurationCalculatorInterceptorProperty(bool exceptionHandlingEnabled)
    {
        ExceptionHandlingEnabled = exceptionHandlingEnabled;
    }

    #region IContributeObjectSink implementation
    public IMessageSink GetObjectSink(MarshalByRefObject o,
    IMessageSink next)
    {
        return new DurationCalculatorAspect(next,ExceptionHandlingEnabled);
    }
    #endregion // IContributeObjectSink implementation

    #region IContextProperty implementation
    // Implement Name, Freeze, IsNewContextOK
    #endregion //IContextProperty implementation


    public void Freeze(Context newContext)
    {
    }

    public bool IsNewContextOK(Context newCtx)
    {
        return true;
    }

    public string Name
    {
        get { return ""; }
    }
}

[AttributeUsage(AttributeTargets.Class)]
public class DurationCalculatorInterceptorAttribute : ContextAttribute
{
    public bool ExceptionHandlingEnabled { get; set; }

    public DurationCalculatorInterceptorAttribute(bool exceptionHandlingEnabled) : base("Security")
    {
        ExceptionHandlingEnabled = exceptionHandlingEnabled;
    }

    public override void GetPropertiesForNewContext(
    IConstructionCallMessage ccm)
    {
        ccm.ContextProperties.Add(new DurationCalculatorInterceptorProperty(ExceptionHandlingEnabled));

    }
}

下面给出了两个使用拦截来记录持续时间和一个用于处理异常的类。这很奇怪,但使用此拦截器处理异常的速度要快28倍。但它仅对记录异常有用。另外,不要忘记继承ContextBoundObject的类。

[DurationCalculatorInterceptor(false)]
public class WithoutExceptionHandling : ContextBoundObject
{
    public void DivideYeahWithoutExceptionHandling()
    {

        for (int i = 0; i < 1000000; i++)
        {
            try
            {
                var x = 2;
                var y = 1;

                var z = x / (y - 1);
            }
            catch (Exception)
            {


            }
        }

    }
}
[DurationCalculatorInterceptor(true)]
public class WithExceptionHandling : ContextBoundObject
{
    public void DivideYeahWithExceptionHandling()
    {
        for (int i = 0; i < 1000000; i++)
        {
            var x = 2;
            var y = 1;
            var z = x / (y - 1);
        }
    }
}