在 PostSharp MethodInterceptionAspect 中使用 StopWatch 的异步方法的性能记录不准确
Inaccurate performance logging of async method using StopWatch inside PostSharp MethodInterceptionAspect
我创建了一个 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;
}
正如@Christian.K所说,您只是在拦截实例化异步任务的方法,而不是异步任务本身。您还使用了方法拦截,它可以完成这项工作,但这并不是您真正需要的模式,因为您实际上并不需要拦截方法执行。你只需要包装方法。
您的案例实际上写在 http://doc.postsharp.net/async-methods#apply-to-state-machine 的文档中。
分析方面:
[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.
下载
有关分析的更多信息,请参阅 http://samples.postsharp.net/ 的 PostSharp.Samples.Profiling 示例。
我创建了一个 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;
}
正如@Christian.K所说,您只是在拦截实例化异步任务的方法,而不是异步任务本身。您还使用了方法拦截,它可以完成这项工作,但这并不是您真正需要的模式,因为您实际上并不需要拦截方法执行。你只需要包装方法。
您的案例实际上写在 http://doc.postsharp.net/async-methods#apply-to-state-machine 的文档中。
分析方面:
[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.
下载有关分析的更多信息,请参阅 http://samples.postsharp.net/ 的 PostSharp.Samples.Profiling 示例。