在代码中构建分析支持

时间:2009-11-27 05:31:29

标签: c# profiling

我希望(我不知道是否可能)在我的代码中构建分析支持,而不是使用一些外部分析器。我听说大多数探查器编写者都使用了一些探查器api。是否可以使用api从正在执行的代码中进行分析?还有其他考虑因素吗?

5 个答案:

答案 0 :(得分:2)

如果您不想使用常规分析器,则可以使用应用程序输出性能计数器。

您可能会发现此博客条目对入门非常有用:http://geekswithblogs.net/.NETonMyMind/archive/2006/08/20/88549.aspx

答案 1 :(得分:2)

EQATEC Profiler构建了一个应用程序的检测版本,它将完全独立地运行和收集分析统计信息 - 您无需附加分析器。默认情况下,您的应用只会将统计信息转储到纯文本xml文件中。

这意味着您可以构建应用的个人资料版本,将其部署在您客户的网站上,让他们运行它并将统计信息报告发回给您。他们无需安装任何特殊的东西或运行探查器或任何东西。

此外,如果您可以通过网络连接访问已部署的应用程序的计算机,并且它允许传入连接,那么您甚至可以自己拍摄正在运行的配置文件应用程序的快照,并与分析器一起坐在家中。你需要的只是一个套接字连接 - 你自己决定端口号,控制协议本身就是普通的http,所以它很可能会让它经过内容过滤网关。

答案 2 :(得分:1)

.NET framework Profiler API是一个COM对象,它在.NET处理它们之前拦截调用。我的理解是它不能托管在托管(C#)代码中。

根据您的目的,您可以插入秒表计时器来测量呼叫长度,或者将性能计数器添加到应用程序中,以便您可以从性能监视器监视应用程序的性能。

答案 3 :(得分:1)

有一篇GameDev文章讨论了如何在C ++程序中构建分析基础结构。您可以调整此方法以使用C#在堆栈上创建的对象在退出时释放而不是为垃圾收集器释放

http://www.gamedev.net/reference/programming/features/enginuity3/

即使你不能采用整个技术,也可能会有一些有用的想法。

答案 4 :(得分:1)

当我无法使用favorite technique时,我所做的就是这个。它很笨拙,并提供低分辨率的信息,但它的工作原理。首先,拥有一个全局字符串堆栈。这是在C中,但您可以将其改编为C#:

int nStack = 0;
char* stack[10000];

然后,在进入和退出每个例程时,您有源代码,按下/弹出例程的名称:

void EveryFunction(){
    int iStack = nStack++; stack[iStack] = "EveryFunction";

    ... code inside function

    nStack = iStack; stack[iStack] = NULL;
}

所以现在stack [0..nStack]保持一个正在运行的调用堆栈(减去调用函数的行号),所以它不如真正的调用堆栈好,但总比没有好。

现在你需要一种方法来随机或伪随机地拍摄它的快照。有另一个全局变量和例程来查看它:

time_t timeToSnap;
void CheckForSnap(){
    time_t now = time(NULL);
    if (now >= timeToSnap){
        if (now - timeToSnap > 10000) timeToSnap = now; // don't take snaps since 1970
        timeToSnap += 1; // setup time for next snapshot
        // print stack to snapshot file
    }
}

现在,在整个代码中调用CheckForSnap,特别是在低级例程中。运行完成后,您将拥有一个堆栈样本文件。您可以查看那些意外行为。例如,显示在大部分样本上的任何函数的包含时间大致等于该分数。

像我说的那样,这比没有好。它确实有缺点:

  • 它不会捕获来自呼叫的行号,因此如果您发现某个功能的时间非常长,您需要在其中搜索耗时的代码。
  • 它增加了它自己的显着开销,即对time(NULL)的所有调用,所以当你删除所有重大问题时,找到小问题就更难了。
  • 如果您的程序花费大量时间等待I / O或用户输入,您将看到在该I / O之后堆积的一堆样本。如果它是文件I / O,这是有用的信息,但如果它是用户输入,你将不得不丢弃这些样本,因为他们所说的只是你需要时间。

理解一些事情很重要:

  • 与流行的公认智慧相反,时间测量的准确性(以及大量样本)并不重要。重要的是样本发生在等待程序完成工作的时候。
  • 与公认的智慧相反,你不是在寻找一个调用图,你不需要关心递归,你不需要关心任何例程需要多少毫秒或者它被调用多少次,而且您不需要关心包容性和排他性时间之间的区别,也不需要关注CPU和挂钟时间之间的区别。对于任何例程,你需要关心的是,它在堆栈上的时间百分比是多少,因为这是它负责的时间,在某种意义上,如果你能以某种方式制造它那个例行公事就没时间了,那就是你的总时间会减少多少。