PostSharp MethodInterceptionAspect内部使用StopWatch对异步方法进行的性能日志记

本文关键字:性能 日志 异步方法 内部 MethodInterceptionAspect StopWatch PostSharp | 更新日期: 2023-09-27 17:58:33

我创建了一个PostSharp方面,它应该记录我使用它的任何方法的执行时间。

然而,它似乎并没有像我预期的那样工作,sw.ElapsedMilliseconds总是在0到3毫秒之间。

[Serializable]
[AttributeUsage(AttributeTargets.Method)]
public sealed class PerfLogAttribute : MethodInterceptionAspect
{
    public override void OnInvoke(MethodInterceptionArgs args)
    {
        var sw = new Stopwatch();
        sw.Start();
        args.Proceed();
        sw.Stop();
        log.Debug(sw.ElapsedMilliseconds);
    }
}

像这样使用:

[PerfLog]
public async Task<bool> DoSomethingAsync() {
    // Adding a delay to test (or call database async)
    await Task.Delay(5000);
    return true;
}

PostSharp MethodInterceptionAspect内部使用StopWatch对异步方法进行的性能日志记

正如@Christian.K所说,您只是截取了实例化异步任务的方法,而不是异步任务本身。您也在使用方法拦截,它可以完成这项工作,但它并不是您所需要的模式,因为您并不真正需要拦截方法执行。你只需要包装这个方法。

您的案例实际上写在文档中http://doc.postsharp.net/async-methods#apply-到状态机。

分析方面:

[Serializable]
public class ProfilingAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Stopwatch sw = Stopwatch.StartNew();
        args.MethodExecutionTag = sw;
    }
    public override void OnExit( MethodExecutionArgs args )
    {
        Stopwatch sw = (Stopwatch) args.MethodExecutionTag;
        sw.Stop();
        Console.WriteLine( "Method {0} executed for {1}ms.",
                           args.Method.Name, sw.ElapsedMilliseconds );
    }
}

应用:

[Profiling( ApplyToStateMachine = true )]
public async Task TestProfiling()
{
    await Task.Delay( 1000 );
    Thread.Sleep( 1000 );
}

如果您在使用Express License的情况下使用PostSharp 4.2,这将不起作用,但在PostSharp 4.3中会起作用,可在https://www.postsharp.net/downloads/postsharp-4.3.

有关评测的更多信息,请参阅PostSharp.Samples.Profileing示例,网址为http://samples.postsharp.net/.