将子时间测量到方法中
Measure sub time into a method
我正在使用 PostSharp 记录某些方法的性能和其他统计信息。我被要求衡量一些子任务的性能和花费的时间,例如调用外部网络服务,或大型数据库等
例如,我有一个应用了 AoPLoggingAttribute 的方法。 AoPLoggingAttribute 继承自 OnMethodBoundaryAspect,因此它支持所有已知方法(OnEntry、OnExit、OnSuccess 等)
[AoPLogging]
public MyClass[] MyMainMethod(string myid)
{
//Some code here
LongExecutingTask();
//Rest of the code here
}
衡量 LongExecutingTask 所用时间的最佳方法是什么?我不在乎它是否是总执行时间的一部分,但不知何故我需要知道从这个任务中花费的时间。
如果你想使用 postsharp,你可以像这样制作一个计时器方面
public class TimingAttribute : OnMethodBoundaryAspect
{
Stopwatch timer = new Stopwatch();
public override void OnEntry(MethodExecutionArgs args)
{
timer.Reset();
timer.Start();
base.OnEntry(args);
}
public override void OnExit(MethodExecutionArgs args)
{
timer.Stop();
Console.WriteLine("Execution took {0} milli-seconds", timer.ElapsedMilliseconds);
base.OnExit(args);
}
}
现在只需将 aspect 附加到您想要计时的方法上即可
[Timing]
public void LongExecutingTask() {}
请记住,postsharp,或一般的 AOP,通过附加到被调用的方法来工作。不是通过添加代码插入您的主要方法(或您调用方法的任何地方)
更新:如果你真的想跟踪整个调用堆栈,你可以这样做
public class TimingAttribute : OnMethodBoundaryAspect
{
static List<Stopwatch> callstack = new List<Stopwatch>();
static int callstackDepth = 0;
public override void OnEntry(MethodExecutionArgs args)
{
var timer = new Stopwatch();
timer.Start();
callstack.Add(timer);
++callstackDepth;
base.OnEntry(args);
}
public override void OnExit(MethodExecutionArgs args)
{
--callstackDepth;
var timer = callstack[callstackDepth];
timer.Stop();
if (callstackDepth == 0) {
//Add code to print out all the results
Console.WriteLine("Execution took {0} milli-seconds", timer.ElapsedMilliseconds);
callstack.Clear();
}
base.OnExit(args);
}
}
现在这只适用于 1 个调用堆栈。如果您的主要方法中有 2 个 LongExecutingTasks,您将不得不考虑如何报告这些任务。但也许这会让您了解如何跟踪整个调用堆栈。
您必须将计时器分配给 MethodExecutionArgs,以便在多线程环境中获得准确的结果。 PostSharp 在内部分配给静态 class,因此任何成员都有被并发调用覆盖的风险。
public class TimingAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
args.MethodExecutionTag = Stopwatch.StartNew();
}
public override void OnExit(MethodExecutionArgs args)
{
var sw = (Stopwatch)args.MethodExecutionTag;
sw.Stop();
System.Diagnostics.Debug.WriteLine("{0} executed in {1} seconds", args.Method.Name,
sw.ElapsedMilliseconds / 1000);
}
}
我正在使用 PostSharp 记录某些方法的性能和其他统计信息。我被要求衡量一些子任务的性能和花费的时间,例如调用外部网络服务,或大型数据库等
例如,我有一个应用了 AoPLoggingAttribute 的方法。 AoPLoggingAttribute 继承自 OnMethodBoundaryAspect,因此它支持所有已知方法(OnEntry、OnExit、OnSuccess 等)
[AoPLogging]
public MyClass[] MyMainMethod(string myid)
{
//Some code here
LongExecutingTask();
//Rest of the code here
}
衡量 LongExecutingTask 所用时间的最佳方法是什么?我不在乎它是否是总执行时间的一部分,但不知何故我需要知道从这个任务中花费的时间。
如果你想使用 postsharp,你可以像这样制作一个计时器方面
public class TimingAttribute : OnMethodBoundaryAspect
{
Stopwatch timer = new Stopwatch();
public override void OnEntry(MethodExecutionArgs args)
{
timer.Reset();
timer.Start();
base.OnEntry(args);
}
public override void OnExit(MethodExecutionArgs args)
{
timer.Stop();
Console.WriteLine("Execution took {0} milli-seconds", timer.ElapsedMilliseconds);
base.OnExit(args);
}
}
现在只需将 aspect 附加到您想要计时的方法上即可
[Timing]
public void LongExecutingTask() {}
请记住,postsharp,或一般的 AOP,通过附加到被调用的方法来工作。不是通过添加代码插入您的主要方法(或您调用方法的任何地方)
更新:如果你真的想跟踪整个调用堆栈,你可以这样做
public class TimingAttribute : OnMethodBoundaryAspect
{
static List<Stopwatch> callstack = new List<Stopwatch>();
static int callstackDepth = 0;
public override void OnEntry(MethodExecutionArgs args)
{
var timer = new Stopwatch();
timer.Start();
callstack.Add(timer);
++callstackDepth;
base.OnEntry(args);
}
public override void OnExit(MethodExecutionArgs args)
{
--callstackDepth;
var timer = callstack[callstackDepth];
timer.Stop();
if (callstackDepth == 0) {
//Add code to print out all the results
Console.WriteLine("Execution took {0} milli-seconds", timer.ElapsedMilliseconds);
callstack.Clear();
}
base.OnExit(args);
}
}
现在这只适用于 1 个调用堆栈。如果您的主要方法中有 2 个 LongExecutingTasks,您将不得不考虑如何报告这些任务。但也许这会让您了解如何跟踪整个调用堆栈。
您必须将计时器分配给 MethodExecutionArgs,以便在多线程环境中获得准确的结果。 PostSharp 在内部分配给静态 class,因此任何成员都有被并发调用覆盖的风险。
public class TimingAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
args.MethodExecutionTag = Stopwatch.StartNew();
}
public override void OnExit(MethodExecutionArgs args)
{
var sw = (Stopwatch)args.MethodExecutionTag;
sw.Stop();
System.Diagnostics.Debug.WriteLine("{0} executed in {1} seconds", args.Method.Name,
sw.ElapsedMilliseconds / 1000);
}
}