当延迟执行变得困难时,如何分析应用程序?

Posted

技术标签:

【中文标题】当延迟执行变得困难时,如何分析应用程序?【英文标题】:How to profile an application when deferred execution makes it difficult? 【发布时间】:2009-10-15 20:36:21 【问题描述】:

我有这个 .NET 应用程序,它依赖于延迟执行。当我对其进行分析时,最耗时的方法是枚举 IEnumerables 的方法。正因为如此,我认为必须优化的方法不在 Top Time Consuming 方法中。

你遇到过吗?在这种情况下如何正确分析应用程序?

【问题讨论】:

延迟投标还是延迟执行? @Andrew 谢谢,我暂时忘记了正确的词。 您使用哪些分析工具? 【参考方案1】:

Jader,如果您可以在 IDE 下运行应用程序并随意暂停它,那么有一种非正统但非常快速有效的方法可以找出时间的原因。有几个人知道,我试着详细解释一下。 Here's my latest attempt. 祝你好运。 Here's another explanation 和 an example。

添加:在您的评论中,您说这正是采样分析器所做的,只是速度更快。即使他们实际上对整个调用堆栈进行了采样,也存在两个大问题:

    他们总结,通常在函数或方法级别,这意味着您必须在耗时的函数中寻找耗时的语句。当您在寻找该信息时,堆栈示例实际上拥有它,但并未向您展示。理由是有太多的样本让你看,所以他们必须总结。但是,如果某个语句在调用堆栈上的某个百分比的时间,例如 50%(不罕见),那么这正是通过删除它可以保存的内容,并且大致是包含它的样本的百分比。 10 个样本与 1000 个样本一样肯定会显示它,因此浪费了额外的样本,并且包含它们的信息的努力只会导致混淆。有的剖析器在语句的层面进行总结,这是一种改进,但它遇到了第二个问题:

    您需要知道执行耗时代码的原因,并且该信息不会显示给您。 信息在那里,在堆栈示例中。如果某部分样本的调用堆栈上有一条语句,则只需查看其中一个或多个样本。调用堆栈为您提供了为什么执行该语句的理由链。既然您知道为什么要这样做,您就可以判断是否有另一种方法来完成同样的事情而不会花费太多时间,例如使用之前调用该语句的缓存数据。一些分析器会为您提供调用树或调用图,但这些都是摘要,这意味着您仍然需要弄清楚为什么这么多时间调用该语句。

我希望这能让您了解我的目的。您必须聚合和测量才能定位问题的一般想法是很自然的想法,但提取包含在少量信息样本中的完整信息要有效得多。

附:不要认为递归是一个问题。递归表现为在某些示例中多次出现的语句。仍然存在这样的情况,即包含该语句的样本部分是对其成本的估计。 (您可能需要考虑一下。)

关于该技术还有其他常见的误解(例如它仅适用于小程序),在上面的链接中进行了探讨。

【讨论】:

【参考方案2】:

在像下面这样的简单应用程序中,对其进行分析并不难。但在更复杂的应用程序中,我还找不到延迟的原因。

以下程序:

static IEnumerable<int> TimeConsuming()

    foreach (var i in Enumerable.Range(0, 10000))
    
        Thread.Sleep(1);
        yield return i;
    


static void Enumerates(IEnumerable<int> enumerable)

    enumerable.ToArray();


static void Main(string[] args)

    var enumerable = TimeConsuming();
    Enumerates(enumerable);

当分析的仪器显示延迟的正确原因时:

函数名称 包含时间 % ConsoleApplication1.Program.Main(string[]) 99.60 ConsoleApplication1.Program.d__0.MoveNext() 99.89

【讨论】:

以上是关于当延迟执行变得困难时,如何分析应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ThreadPool 中延迟执行?

PostgreSQL:如何在不延迟插入响应的情况下执行插入触发器?

Oracle 延时执行问题求指教:

当方法执行更新时刷新延迟加载的 Primefaces 数据表

Hibernate延迟加载

Hibernate延迟加载