-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Use butil::ThreadLocal to store keytable #2645
New issue
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
Changes from all commits
b339a7b
c707aa3
ddb253f
0fb0655
d279324
c2bc88b
98edccf
efcaba7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| #include <pthread.h> | ||
| #include "butil/macros.h" | ||
| #include "butil/atomicops.h" | ||
| #include "butil/thread_key.h" | ||
| #include "bvar/passive_status.h" | ||
| #include "bthread/errno.h" // EAGAIN | ||
| #include "bthread/task_group.h" // TaskGroup | ||
|
|
@@ -204,14 +205,56 @@ class BAIDU_CACHELINE_ALIGNMENT KeyTable { | |
| SubKeyTable* _subs[KEY_1STLEVEL_SIZE]; | ||
| }; | ||
|
|
||
| struct KeyTableList { | ||
| KeyTableList() { | ||
| keytable = NULL; | ||
| } | ||
| ~KeyTableList() { | ||
| bthread::TaskGroup* g = bthread::tls_task_group; | ||
| bthread::KeyTable* old_kt = bthread::tls_bls.keytable; | ||
| while (keytable) { | ||
| bthread::KeyTable* kt = keytable; | ||
| keytable = kt->next; | ||
| bthread::tls_bls.keytable = kt; | ||
| if (g) { | ||
| g->current_task()->local_storage.keytable = kt; | ||
| } | ||
| delete kt; | ||
| if (old_kt == kt) { | ||
| old_kt = NULL; | ||
| } | ||
| g = bthread::tls_task_group; | ||
| } | ||
| bthread::tls_bls.keytable = old_kt; | ||
| if(g) { | ||
| g->current_task()->local_storage.keytable = old_kt; | ||
| } | ||
| } | ||
| KeyTable* keytable; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. class 类型不建议直接把成员暴露成public,要么改成struct,要么封装成getter/setter
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 改成了struct |
||
| }; | ||
|
|
||
| static KeyTable* borrow_keytable(bthread_keytable_pool_t* pool) { | ||
| if (pool != NULL && pool->free_keytables) { | ||
| BAIDU_SCOPED_LOCK(pool->mutex); | ||
| KeyTable* p = (KeyTable*)pool->free_keytables; | ||
| if (p) { | ||
| pool->free_keytables = p->next; | ||
| if (pool != NULL && (pool->list || pool->free_keytables)) { | ||
| KeyTable* p; | ||
| pthread_rwlock_rdlock(&pool->rwlock); | ||
| auto list = (butil::ThreadLocal<bthread::KeyTableList>*)pool->list; | ||
| if (list && list->get()->keytable) { | ||
| p = list->get()->keytable; | ||
| list->get()->keytable = p->next; | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| return p; | ||
| } | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| if (pool->free_keytables) { | ||
| pthread_rwlock_wrlock(&pool->rwlock); | ||
| p = (KeyTable*)pool->free_keytables; | ||
| if (p) { | ||
| pool->free_keytables = p->next; | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| return p; | ||
| } | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| } | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
@@ -226,14 +269,16 @@ void return_keytable(bthread_keytable_pool_t* pool, KeyTable* kt) { | |
| delete kt; | ||
| return; | ||
| } | ||
| std::unique_lock<pthread_mutex_t> mu(pool->mutex); | ||
| pthread_rwlock_rdlock(&pool->rwlock); | ||
| if (pool->destroyed) { | ||
| mu.unlock(); | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| delete kt; | ||
| return; | ||
| } | ||
| kt->next = (KeyTable*)pool->free_keytables; | ||
| pool->free_keytables = kt; | ||
| auto list = (butil::ThreadLocal<bthread::KeyTableList>*)pool->list; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 全局free_keytables里的kt一旦被借走就永远还不回去free_keytables了吗?这样keytables的复用率会降低吧,如果线程数很多,可能会占用更多的内存
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 是不会返回给free_keytables了。free_keytables的大小是根据server.option的reserved_thread_local_data变量设置的,默认为0。 |
||
| kt->next = list->get()->keytable; | ||
| list->get()->keytable = kt; | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| } | ||
|
|
||
| static void cleanup_pthread(void* arg) { | ||
|
chenBright marked this conversation as resolved.
|
||
|
|
@@ -279,7 +324,8 @@ int bthread_keytable_pool_init(bthread_keytable_pool_t* pool) { | |
| LOG(ERROR) << "Param[pool] is NULL"; | ||
| return EINVAL; | ||
| } | ||
| pthread_mutex_init(&pool->mutex, NULL); | ||
| pthread_rwlock_init(&pool->rwlock, NULL); | ||
| pool->list = new butil::ThreadLocal<bthread::KeyTableList>(); | ||
| pool->free_keytables = NULL; | ||
| pool->destroyed = 0; | ||
| return 0; | ||
|
|
@@ -291,16 +337,16 @@ int bthread_keytable_pool_destroy(bthread_keytable_pool_t* pool) { | |
| return EINVAL; | ||
| } | ||
| bthread::KeyTable* saved_free_keytables = NULL; | ||
| { | ||
| BAIDU_SCOPED_LOCK(pool->mutex); | ||
| if (pool->free_keytables) { | ||
| saved_free_keytables = (bthread::KeyTable*)pool->free_keytables; | ||
| pool->free_keytables = NULL; | ||
| } | ||
| pool->destroyed = 1; | ||
| } | ||
| pthread_rwlock_wrlock(&pool->rwlock); | ||
| pool->destroyed = 1; | ||
| delete (butil::ThreadLocal<bthread::KeyTableList>*)pool->list; | ||
| saved_free_keytables = (bthread::KeyTable*)pool->free_keytables; | ||
| pool->list = NULL; | ||
| pool->free_keytables = NULL; | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
|
|
||
| // Cheat get/setspecific and destroy the keytables. | ||
| bthread::TaskGroup* const g = bthread::tls_task_group; | ||
| bthread::TaskGroup* g = bthread::tls_task_group; | ||
| bthread::KeyTable* old_kt = bthread::tls_bls.keytable; | ||
| while (saved_free_keytables) { | ||
| bthread::KeyTable* kt = saved_free_keytables; | ||
|
|
@@ -310,9 +356,7 @@ int bthread_keytable_pool_destroy(bthread_keytable_pool_t* pool) { | |
| g->current_task()->local_storage.keytable = kt; | ||
| } | ||
| delete kt; | ||
| if (old_kt == kt) { | ||
| old_kt = NULL; | ||
| } | ||
| g = bthread::tls_task_group; | ||
| } | ||
| bthread::tls_bls.keytable = old_kt; | ||
| if (g) { | ||
|
|
@@ -330,11 +374,12 @@ int bthread_keytable_pool_getstat(bthread_keytable_pool_t* pool, | |
| LOG(ERROR) << "Param[pool] or Param[stat] is NULL"; | ||
| return EINVAL; | ||
| } | ||
| std::unique_lock<pthread_mutex_t> mu(pool->mutex); | ||
| pthread_rwlock_rdlock(&pool->rwlock); | ||
| size_t count = 0; | ||
| bthread::KeyTable* p = (bthread::KeyTable*)pool->free_keytables; | ||
| for (; p; p = p->next, ++count) {} | ||
| stat->nfree = count; | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| return 0; | ||
| } | ||
|
|
||
|
|
@@ -365,14 +410,15 @@ void bthread_keytable_pool_reserve(bthread_keytable_pool_t* pool, | |
| kt->set_data(key, data); | ||
| } // else append kt w/o data. | ||
|
|
||
| std::unique_lock<pthread_mutex_t> mu(pool->mutex); | ||
| pthread_rwlock_wrlock(&pool->rwlock); | ||
| if (pool->destroyed) { | ||
| mu.unlock(); | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| delete kt; | ||
| break; | ||
| } | ||
| kt->next = (bthread::KeyTable*)pool->free_keytables; | ||
| pool->free_keytables = kt; | ||
| pthread_rwlock_unlock(&pool->rwlock); | ||
| if (data == NULL) { | ||
| break; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.