-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
bthread task group add tag #2358
Conversation
这个是划分线程池的一个新的想法,我觉得这样实现对性能损失最少,现在提上来的代码是一个DEMO,总结一下: |
1ff809d
to
9998367
Compare
进一步,是不是可以像flare一样支持NUMA架构? |
|
d65c234
to
c70890f
Compare
ad2fc96
to
0fad86c
Compare
@wwbmmm 再review评估一下吧,看起来有需求的用户还挺多的。 |
坐等合入 |
@justmao945 @yanglimingcn @wwbmmm 我请教个小问题,大机型下,如果划分容器时直接绑定numa,这样就没有 remote access 了。在软件层面实现 numa aware 似乎只能逼近这个状态。所以为什么不直接用容器绑定numa?是因为内存的限制吗?还是因为有些场景不能接受使用容器,必须要用物理整机? |
c8616de
to
8dd7426
Compare
的确有些场景不能或者不方便使用容器,我所接触的,比如,一些使用了dpdk、spdk、rdma等等这些对性能要求比较极致的应用,都绕过了内核,相当于自己直接管理硬件了。 |
大内存应用 😢 |
8dd7426
to
4963aa3
Compare
@yanglimingcn 大佬请教个问题,我在你代码基础上修改了一下,一个server内部分service,然后每个service绑定一个bthread group tag,收到消息后根据tag进行分发。现在有一个问题,发现bthread_count监控数值不对,比如3个tag,总和是对的,但是有些group tag不对,看起来应该是task原来在group1上运行,但是退出是跑到group2上:
我的处理是在
tag是service注册时打上的。 |
你这个func_cp里面执行什么内容了呢,如果执行done->Run可能会有tag切换吧,因为你这么改的话,epoll_wait这个线程只能属于tag0吧,所以它的执行上下文都是tag0的。 |
done我感觉应该没问题的,是跑在对应tag的bthread里面,这个func_cp就是调用服务端的代码了。我合一下 #2476 这个PR再试试 |
@yanglimingcn 我知道问题所在了,的确是done的调用问题,我们用了另外一个braft的库,里面调用done是塞入到bthread::ExecutionQueue里面,这块代码没有改导致的。 |
请问这个PR的改动,如果使用了bthread::ExecutionQueue,ExecutionQueue里面的任务如何区分按照哪个tag去调度的呢? 还是整个ExecutionQueue对应于一个tag呢? |
最好还是一个tag启动一个execq比较合适 |
启动ExecutionQueue的时候,在attr里面指定上tag,就是整个ExecutionQueue都会在这个tag所在的线程池里执行了是么? |
1、execq会启动协程,这个协程设置好attribute的tag就可以了 |
感觉ExecutionQueue这个用起来还是有点问题,比如in_place执行的场景,task是在当前bthread执行的,就有可与初始化execq时指定的attr的tag不一致,如果task里面用到了bthread_mutex,就可能存在跨线程池唤醒的问题。 在我们的项目里面还有一个场景,感觉也有可能有问题,具体如下: 由于对外服务和braft使用了不同的tag,braft的on_apply调用是在execq中执行,按这个PR前面的讨论,会指定attr的tag为braft使用的tag,那么on_apply执行所使用的bthread就会是braft的tag,在on_apply中调用bthread_cond_signal,就会发生跨线程池使用bthread同步原语的问题了。 如果是这种场景,根据前面的讨论,应该是不适合让对外服务和braft服务使用不同的tag来调度了。不知道这样的理解是否正确? |
划分线程池的目的是为了隔离,感觉你对外服务和braft已经在上层通过execq做了隔离,是不是就没必要再使用这个功能了呢? |
braft目前用起来有一个有点棘手的问题,每个raft group都会开启4个execq,包括fsm caller、log manager、node apply、raft meta。当raft group数量比较多,或者fsm caller中有长耗时操作,或者fsm caller的调用内有pthread阻塞,braft实际上就会把brpc的所有线程用满,导致整个进程都无法处理新的message,导致braft本身的心跳也会超时。 如前文所述,对外服务的业务逻辑涉及到写braft状态机,并等待fsm caller执行完成后的callback再返回response给调用方。因此就会存在对外服务的线程池与braft的execq之间需要使用bthread同步原语。除了这种情况之外,服务本身还有一些业务逻辑的处理也涉及到提交raft状态机等待状态写入成功后才能继续执行的逻辑,也会涉及到跨线程池同步。 表达能力比较差,可能描述得不好:)。
这个地方比较难处理的点是braft的逻辑几乎都是通过execq来执行的,当execq的数量变大之后,实际上一个execq就相当于一个并发,可以跑满一个线程。execq数量多了之后,线程数就不够用了,这个问题是最早希望使用tag调度来限制braft使用的资源的一个主要原因。但是使用了tag调度之后,跨线程池使用bthread原语又会有问题,就有点不好处理。 我们现在通过一些方法已经基本实现了控制braft的并发度了,结合tag调度这个feature,应该能扩展一些新的方法来做这个事情。 技术上bthread原语跨线程池的使用,以后是否有办法支持呢? |
技术上是能实现的,但是做起来也有些复杂,同步的代码确实更好一些,否则execq里面就得调用callback了吧? |
确实还是有同步代码的需求。有些场景如果用callback,就会使callback里的逻辑很重,虽然技术上是可以的,但是代码看起来就很难看了。 |
ok,这块后续可以支持。 |
@yanglimingcn 我有几个疑问。比如我有一个server,tag是tag1。
|
是的 |
|
What problem does this PR solve?
Issue Number:
Problem Summary:
What is changed and the side effects?
Changed:
Side effects:
Performance effects(性能影响):
Breaking backward compatibility(向后兼容性):
Check List: