如何可视化常规调用堆栈并计算内部和外部执行时间非常明显。但是,如果处理过协程,调用堆栈可能看起来很混乱。我的意思是,协程可能不会将执行交给它的父级,而是交给另一个协同程序(例如greenlet)。是否有一些常用方法可以为此类场景提供一致的分析输出?
1 回答
考虑同时为所有线程堆栈的单个样本。
你需要知道的是——谁在等谁,为什么。通常,如果函数 A 在堆栈上高于 B,则表示 A 正在等待 B 返回,原因是 A 想让 B 做某事。如果您查看整个堆栈,对于一个线程,您会得到一连串原因,为什么该特定纳秒被该线程花费。如果您正在寻找速度,那么您正在寻找完全不需要的原因链(因为存在薄弱环节)。即使链以 I/O 结束,这也有效。如果是用户输入,它只是在等待用户。但是,如果它是输出、磁盘 I/O 或普通的旧 CPU 启动,您也许可以做一些事情来减少它,并获得性能提升(如果您在 2 个或更多样本上看到相同的问题)。
如果线程 A 正在等待线程 B 怎么办?那么你在 A 的栈底看到的是一个等待另一个线程的函数。你需要弄清楚哪个是线程 B,并查看它的堆栈,因为它花费的时间越长,A 花费的时间就越长。所以这更难,但你肯定不害怕。
我在这里谈论的是手动分析,您可以自己在调试器中获取样本,然后将全部注意力集中在每个样本上。分析工具倾向于假设您很懒惰并且只想要数字,如果这些数字中没有任何内容,您会很高兴,因为您什么也没找到。事实上,如果一些愚蠢且不必要的活动占用了 30% 的时间,那么平均而言,您需要查看两次的样本数是 2/0.3 = 6.67 个样本(不是一个大数字),您很可能会看到它,探查器不会。那是随机暂停。