apache / brpc

brpc is an Industrial-grade RPC framework using C++ Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. "brpc" means "better RPC".
https://brpc.apache.org
Apache License 2.0
16.05k stars 3.92k forks source link

keytable管理问题咨询 #2635

Open MJY-HUST opened 2 months ago

MJY-HUST commented 2 months ago

目前bthread中对于bthread_local的管理是每个bthread会维护一个keytable。如果bthread_attr_t中设置有bthread_keytable_pool_t,那么bthread结束后只会return keytable而不会销毁,在第一次调用bthread_getspecific获取bthread_local变量时可以borrow_keytable;否则每当第一次访问bthread_local变量时和bthread结束时均需要构造/销毁keytable。

然而,即使是使用bthread_keytable_pool_t管理keytable,由于bthread_keytable_pool_t结构是一个用pthread_mutex_t维护的单链表格式,每次return/borrow都需要加锁。在bthread执行流程较短且需要访问bthread_local变量的场景下,锁的竞争会显著影响性能。

一个想法是将keytable嵌入task_meta一同由task_meta所属的resource_pool管理,当task_meta构造时初始化keytable指针为空,第一次需要使用keytbale时构造,并赋值给task_meta.local_storage. keytable,task_meta析构时销毁keytable。keytable只会在task_meta析构时销毁,理论上增加的内存使用量=存活的bthread个数的峰值*bthread_key_t的个数*平均一个value的大小。

chenBright commented 1 month ago

第一次需要使用keytbale时构造,并赋值给task_meta.local_storage. keytable,task_meta析构时销毁keytable。

我理解这是为了尽量复用、减少构造、不加锁。TaskMeta是从ResourcePool分配出来的,在进程运行的时候,不会释放TaskMeta的吧。那么一旦使用了KeyTable,TaskMeta就会绑定一个KeyTable,跟bthread_keytable_pool_t机制是不是有点兼容问题?例如一个TaskMeta已经绑定一个KeyTable,但是bthread_attr_t设置bthread_keytable_pool_t,这时候还需要额外的状态来记录KeyTable的来源用于处理归还逻辑吧。

是不是用ObjectPool来分配KeyTable就能规避锁的影响,实现还简单?

MJY-HUST commented 1 month ago

第一次需要使用keytbale时构造,并赋值给task_meta.local_storage. keytable,task_meta析构时销毁keytable。

我理解这是为了尽量复用、减少构造、不加锁。TaskMeta是从ResourcePool分配出来的,在进程运行的时候,不会释放TaskMeta的吧。那么一旦使用了KeyTable,TaskMeta就会绑定一个KeyTable,跟bthread_keytable_pool_t机制是不是有点兼容?例如一个TaskMeta已经绑定一个KeyTable,但是bthread_attr_t设置bthread_keytable_pool_t,这时候还需要额外的状态来记录KeyTable的来源用于处理归还逻辑吧。

是不是用ObjectPool来分配KeyTable就能规避锁的影响,实现还简单?

是的,前面说的逻辑和bthread_keytable_pool_t机制有重合。 感觉把bthread_keytable_pool_t替换为ObjectPool来管理KeyTable比较合适