We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is your feature request related to a problem? (你需要的功能是否与某个问题有关?)
相关isue:#2389
gdb(ptrace)+gdb_bthread_stack.py主要的缺点是要慢和阻塞进程,需要一种高效的追踪bthread调用栈的方法。
bRPC框架的协作式用户态协程无法像Golang内建的抢占式协程一样实现高效的STW(Stop the World),框架也无法干预用户逻辑的执行,所以要追踪bthread调用栈是比较困难的。
在线追踪bthread调用栈需要解决以下问题:
Describe the solution you'd like (描述你期望的解决方法)
以下是目前的bthread状态模型。
为了解决上述两个问题,该方案实现了STB(Stop The Bthread),核心思路可以简单总结为,在追踪bthread调用栈的过程中,状态不能流转到当前追踪方法不支持的状态。STB包含了两种追踪模式:上下文(context)追踪模式和信号追踪模式。
上下文追踪模式可以追踪挂起bthread的调用栈。挂起的bthread栈是稳定的,利用TaskMeta.stack中保存的上下文信息(x86_64下关键的寄存器主要是RIP、RSP、RBP),通过一些可以回溯指定上下文调用栈的库来追踪bthread调用栈。但是挂起的bthread随时可能会被唤醒,执行逻辑(包括jump_stack),则bthread栈会一直变化。不稳定的上下文是不能用来追踪调用栈的,需要在jump_stack前拦截bthread的调度,等到调用栈追踪完成后才继续运行bthread。所以,上下文追踪模式支持就绪、挂起这两个状态。
目前调研到,支持回溯指定上下文调用栈的库有gpertools、abseil-cpp和libunwind,其中:
综合考虑,选择libunwind。
信号追踪模式可以追踪运行中bthread的调用栈。运行中bthread是不稳定的,不能使用TaskMeta.stack来追踪bthread调用栈。只能另辟蹊径,使用信号中断bthread运行逻辑,在信号处理函数中回溯bthread调用栈。使用信号有两个问题:
所以,追踪模式只支持运行状态。
jump_stack是bthread挂起或者运行的必经之路,也是STB的拦截点。STB将状态分成三类:
以下是引入STB后的bthread状态模型,在原来bthread状态模型的基础上,加入两个状态(拦截点):将运行、挂起中。
为了实现状态流转,在TaskMeta中增加一个butil::atomic<BthreadStatus> status,表示bthread状态,状态流转是原子的(CAS)。开始追踪的时候,status=-status,变成负值;结束的时候,status=-status,变会正值,即用status的最高位作为追踪的标识。
butil::atomic<BthreadStatus> status
enum BthreadStatus { BTHREAD_STATUS_CREATED = 0, // 创建 BTHREAD_STATUS_READY, // 就绪 BTHREAD_STATUS_PRE_RUN, // 将运行 BTHREAD_STATUS_RUNNING, // 运行 BTHREAD_STATUS_SUSPENDING, // 挂起中 BTHREAD_STATUS_SUSPENDED, // 挂起 BTHREAD_STATUS_END, // 销毁 };
经过上述分析,总结出STB的流程:
正常情况下,不会追踪bthread调用栈,该特性只是增加了记录状态流转的原子操作(CAS)。所以,可以先测试一下状态流转CAS的性能消耗:
Describe alternatives you've considered (描述你想到的折衷方案)
Additional context/screenshots (更多上下文/截图)
The text was updated successfully, but these errors were encountered:
@wwbmmm 有空帮忙评估一下
Sorry, something went wrong.
赞,这个功能打算怎么使用呢?通过内置服务查看调用栈?还是将栈打印到日志中?
这个可以考虑做成编译开关,如果不用的话就不需要引入新的编译依赖
通过BthreadsService查看调用栈。对于不适用内置服务的场景,可以调接口获取调用栈。
综合考虑,选择libunwind。 这个可以考虑做成编译开关,如果不用的话就不需要引入新的编译依赖
嗯,是打算搞个编译开关,按需打开。
No branches or pull requests
Is your feature request related to a problem? (你需要的功能是否与某个问题有关?)
相关isue:#2389
gdb(ptrace)+gdb_bthread_stack.py主要的缺点是要慢和阻塞进程,需要一种高效的追踪bthread调用栈的方法。
bRPC框架的协作式用户态协程无法像Golang内建的抢占式协程一样实现高效的STW(Stop the World),框架也无法干预用户逻辑的执行,所以要追踪bthread调用栈是比较困难的。
在线追踪bthread调用栈需要解决以下问题:
Describe the solution you'd like (描述你期望的解决方法)
bthread状态模型
以下是目前的bthread状态模型。
设计方案
核心思路
为了解决上述两个问题,该方案实现了STB(Stop The Bthread),核心思路可以简单总结为,在追踪bthread调用栈的过程中,状态不能流转到当前追踪方法不支持的状态。STB包含了两种追踪模式:上下文(context)追踪模式和信号追踪模式。
上下文(context)追踪模式
上下文追踪模式可以追踪挂起bthread的调用栈。挂起的bthread栈是稳定的,利用TaskMeta.stack中保存的上下文信息(x86_64下关键的寄存器主要是RIP、RSP、RBP),通过一些可以回溯指定上下文调用栈的库来追踪bthread调用栈。但是挂起的bthread随时可能会被唤醒,执行逻辑(包括jump_stack),则bthread栈会一直变化。不稳定的上下文是不能用来追踪调用栈的,需要在jump_stack前拦截bthread的调度,等到调用栈追踪完成后才继续运行bthread。所以,上下文追踪模式支持就绪、挂起这两个状态。
目前调研到,支持回溯指定上下文调用栈的库有gpertools、abseil-cpp和libunwind,其中:
综合考虑,选择libunwind。
信号追踪模式
信号追踪模式可以追踪运行中bthread的调用栈。运行中bthread是不稳定的,不能使用TaskMeta.stack来追踪bthread调用栈。只能另辟蹊径,使用信号中断bthread运行逻辑,在信号处理函数中回溯bthread调用栈。使用信号有两个问题:
所以,追踪模式只支持运行状态。
小结
jump_stack是bthread挂起或者运行的必经之路,也是STB的拦截点。STB将状态分成三类:
详细流程
以下是引入STB后的bthread状态模型,在原来bthread状态模型的基础上,加入两个状态(拦截点):将运行、挂起中。
为了实现状态流转,在TaskMeta中增加一个
butil::atomic<BthreadStatus> status
,表示bthread状态,状态流转是原子的(CAS)。开始追踪的时候,status=-status,变成负值;结束的时候,status=-status,变会正值,即用status的最高位作为追踪的标识。经过上述分析,总结出STB的流程:
性能
正常情况下,不会追踪bthread调用栈,该特性只是增加了记录状态流转的原子操作(CAS)。所以,可以先测试一下状态流转CAS的性能消耗:
其他
Describe alternatives you've considered (描述你想到的折衷方案)
Additional context/screenshots (更多上下文/截图)
The text was updated successfully, but these errors were encountered: