是否有一些常用技术来分析基于协程的代码?
Are there some common techniques to profile coroutine based code?
如何可视化常规调用堆栈并计算内部和外部执行时间是非常明显的。但是,如果处理过协程,调用堆栈可能看起来非常混乱。我的意思是,协程可能不会将执行交给它的父级,而是交给另一个协程(例如 greenlet)。是否有一些通用方法可以为此类场景制作一致的分析输出?
同时考虑所有线程堆栈的单个样本。
您需要知道的是 - 谁在等谁,为什么。
通常,如果函数 A 在堆栈上位于 B 之上,则表示 A 正在等待 B return,原因是 A 要 B 做某事。
如果您查看整个堆栈,对于一个线程,您会得到该线程花费该特定纳秒的一系列原因。
如果您正在寻找速度,那么您正在寻找一连串的原因,而这些原因完全不是您真正需要的(因为有一个弱 link)。
即使链以 I/O 结尾,这仍然有效。
如果是用户输入,它只是在等待用户。
但是如果它是输出,或者磁盘 I/O,或者普通的旧 CPU 启动,你可以做一些事情来减少它,并获得性能提升(如果你在 2 个或更多个上看到同样的问题样本)。
如果线程 A 正在等待线程 B 怎么办?
然后你在A的栈底看到的是一个等待其他线程的函数。
你需要弄清楚哪个是线程B,然后查看its堆栈,因为it花费的时间越长,A花费的时间就越长。
所以这个比较难,但是你肯定不怕。
我在这里谈论的是手动分析,您自己在调试器中采集样本,然后全神贯注于每个样本。
剖析工具往往假设您很懒惰,只想要数字,如果没有从这些数字中跳出,您会很高兴,因为您什么也没找到。
事实上,如果一些愚蠢的不必要的 activity 占用了 30% 的时间,那么平均而言,你需要看到它两次的样本数是 2/0.3 = 6.67 个样本(不是一个大数字),这是相当大的您可能会看到它并且 the profiler will not。
那是 random pausing.
如何可视化常规调用堆栈并计算内部和外部执行时间是非常明显的。但是,如果处理过协程,调用堆栈可能看起来非常混乱。我的意思是,协程可能不会将执行交给它的父级,而是交给另一个协程(例如 greenlet)。是否有一些通用方法可以为此类场景制作一致的分析输出?
同时考虑所有线程堆栈的单个样本。
您需要知道的是 - 谁在等谁,为什么。 通常,如果函数 A 在堆栈上位于 B 之上,则表示 A 正在等待 B return,原因是 A 要 B 做某事。 如果您查看整个堆栈,对于一个线程,您会得到该线程花费该特定纳秒的一系列原因。 如果您正在寻找速度,那么您正在寻找一连串的原因,而这些原因完全不是您真正需要的(因为有一个弱 link)。 即使链以 I/O 结尾,这仍然有效。 如果是用户输入,它只是在等待用户。 但是如果它是输出,或者磁盘 I/O,或者普通的旧 CPU 启动,你可以做一些事情来减少它,并获得性能提升(如果你在 2 个或更多个上看到同样的问题样本)。
如果线程 A 正在等待线程 B 怎么办? 然后你在A的栈底看到的是一个等待其他线程的函数。 你需要弄清楚哪个是线程B,然后查看its堆栈,因为it花费的时间越长,A花费的时间就越长。 所以这个比较难,但是你肯定不怕。
我在这里谈论的是手动分析,您自己在调试器中采集样本,然后全神贯注于每个样本。 剖析工具往往假设您很懒惰,只想要数字,如果没有从这些数字中跳出,您会很高兴,因为您什么也没找到。 事实上,如果一些愚蠢的不必要的 activity 占用了 30% 的时间,那么平均而言,你需要看到它两次的样本数是 2/0.3 = 6.67 个样本(不是一个大数字),这是相当大的您可能会看到它并且 the profiler will not。 那是 random pausing.