【开发日志】第十四周:编写异步函数跟踪方案 #19
chenzhiy2001
announced in
Announcements
Replies: 1 comment
-
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
背景
Rust 等语言的异步运行时采用了 Cooperating scheduling,因此是一套 non-preemptive 的系统,可能出现某个异步任务运行过久的情况。
目标
我们希望找到这样的异步任务,从而帮助开发者减少异步代码的运行时长。
预期成果
操作系统异步任务的火焰图
方法
Rust 编译器会将异步代码分割成多个嵌套的Future。但是根据 石尚峰学长的工作,跟踪所有的 Future 比较困难。
考虑到异步运行时(具体来说,是异步运行时的executor)会将几个 Future 打包成一个 task 来运行,跟踪所有 task 的执行时间也能达到我们的目标。
因此,我们不试图跟踪所有 Future,而是跟踪 Task+尽可能多的 Future。
就算有的 Future 被 inline 了也不影响达到我们的目标,因为被inline的Future的上一层 Future 或者 上一层 Task 是能跟踪到的,根据高层 Future/Task 的执行时长我们仍然能找到执行时间过长的异步代码。所以跟踪 Task 可以起到“兜底”的作用。
跟踪 Task + Future (以 async-std 为例)
主函数以外的 Task 都是由形如
_<async_std..task..builder..SupportTaskLocals<F> as..
的函数创建的,且每一个这样的函数都对应一个 Task。因此,给这些函数的调用和返回指令插桩,即可获得这个 Task 的执行时长。对于
async/await
生成的 Future,跟踪形如_<core..future..from_generator..GenFuture<T> as..
的函数的调用和返回时间。对于用户自定义的Future(比如用
impl
记号实现的),跟踪形如USER_IMPLMENTED_FUTURE as core..future..future..Future
的函数的调用和返回时间。对于异步代码块和异步闭对应的匿名Future(这些匿名Future都嵌套在Task里),跟踪形如
ASYNC_FUNC_NAME::_{{closure}}
的函数的调用和返回时间。如果还有其他来源的 Future,同样找到它们对应的的创建函数的调用/返回时间即可。
除了调用和返回时间,我们还利用栈回溯记录这些函数在栈内的深度,从而分析出这些 Task/Future 的嵌套关系。
有了上述调用时间+返回时间+嵌套关系,我们就可以画出火焰图了。
跟踪 zCore 的例子
chenzhiy2001/zCore@bec0cf7 (怀疑栈回溯的深度是错的,因此暂时没去画火焰图,但是大致流程走通了)
已知问题
参考资料
Beta Was this translation helpful? Give feedback.
All reactions