将子时间测量为方法

时间:2016-03-09 12:53:38

标签: performance statistics postsharp stopwatch

我正在使用PostSharp来记录某些方法的性能和其他统计信息。我被要求测量一些子任务的性能和时间,例如调用外部Web服务或大型数据库等。

例如,我有一个应用了AoPLoggingAttribute的方法。 AoPLoggingAttribute继承自OnMethodBoundaryAspect,因此它支持所有已知方法(OnEntry,OnExit,OnSuccess等)

    [AoPLogging]
    public MyClass[] MyMainMethod(string myid)
    {
        //Some code here
        LongExecutingTask();
        //Rest of the code here
    }

衡量LongExecutingTask所用时间的最佳方法是什么?我不在乎它是否是总执行时间的一部分,但不知怎的,我需要知道从这项任务中抽出的时间。

2 个答案:

答案 0 :(得分:1)

如果你想使用postharp,你可以制作像这样的计时器方面

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);
    }
}

现在只需将方面附加到您想要计时的方法

[Timing]
public void LongExecutingTask() {}

请记住,postharp或AOP通常通过附加到被调用的方法来工作。不是通过添加代码插入主方法(或者您调用方法)

更新:如果你真的想跟踪整个callstack,你可以做这样的事情

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个单一的callstack。如果您在主方法中有2个LongExecutingTasks,则必须考虑如何报告。但也许这会让你知道如何跟踪整个callstack。

答案 1 :(得分:1)

您必须将计时器分配给MethodExecutionArgs,以便在多线程环境中获得准确的结果。 PostSharp在内部分配给静态类,因此任何成员都有被并发调用覆盖的风险。

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);
    }
}