使用Proxy类进行自我概要分析

时间:2009-02-15 22:56:17

标签: c# performance profiling

给定一个接口

public interface IValueProvider
{
  object GetValue(int index);
}

和IValueProvider实例的树结构类似于数学表达式树。 我想测量在没有外部探查器的情况下在运行时在每个节点的GetValue方法中花费的时间。

GetValue可以在设计时做任何我不知道的事情:收集其他IValueProviders的值,运行IronPython表达式甚至是外部插件。我想向用户提供有关节点计时的统计信息。

为此,我可以创建一个包装IValueProvider的代理类:

public class ValueProviderProfiler : IValueProvider
{
  private IValueProvider valueProvider;

  public object GetValue(int index)
  {
    // ... start measuring
    try
    {
      return this.valuepProvider.GetValue(index);
    }
    finally
    {
      // ... stop measuring
    }
  }
}

测量节点在没有外部过程引起的失真的情况下花费的时间的最佳方法是什么,具有良好的准确性并且与并行评估节点的事实有关?

仅仅使用Stopwatch类是行不通的,看看进程的处理器时间并不考虑cpu时间可能已在另一个节点上消耗的事实。

2 个答案:

答案 0 :(得分:1)

如果您正在尝试分析性能而不是从给定方法开始,请获取像Ants profiler这样的实际配置文件,并查看真正的瓶颈所在。很多时候,当你假设为什么你的应用程序不具备高效性时,你最终会查找并优化所有错误的地方并浪费大量时间。

答案 1 :(得分:0)

你没有说你期望每个GetValue电话完成的速度有多快,所以很难给出明确的建议......

对于需要几毫秒(磁盘访问,填写控件,网络传输等)的事情,我使用了DateTime.Ticks.Now。它似乎工作得相当好,声称每秒10,000,000滴答的分辨率听起来相当不错。 (我怀疑它确实非常精确;我不知道它支持哪种设施。)

我不知道有什么办法可以避免执行其他进程引起的扭曲。我通常只花费平均时间来运行我感兴趣的每个特定部分,平均尽可能多的运行(以消除由其他进程和任何计时器不准确引起的变化)。

(在本机代码中,为了分析不需要很长时间执行的事情,我通过RDTSC指令使用CPU循环计数器。所以如果你为其他定时器计时太快了获得一个有用的读数,但没有那么快完成调用开销是一个问题,你不介意在CPU周期而不是任何标准时间单位获取读数,可能值得写一个返回的本机函数UInt64中的循环计数器值。虽然我自己也不需要在托管代码中执行此操作。)