From 15edd69ddf649ebf7ecab3fa72bc5dea263c0154 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub <wlad@mariadb.com> Date: Tue, 11 Oct 2022 00:07:38 +0200 Subject: [PATCH] MDEV-27943 Reduce overhead of attaching THD to OS thread, in threadpool Avoid relatively expensive THD::store_globals() for every query in the threadpool. Use a lighter version instead, that only resets some thread local storage variables(THD, mysys, PSI), avoids some calculationms and caches syscall gettid (Linux only) in a thread_local variable. Also simplify Worker_context use, with RAII. --- sql/threadpool_common.cc | 54 ++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 965432357be..78f9eaf8792 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -92,13 +92,13 @@ struct Worker_thread_context PSI_thread *psi_thread; st_my_thread_var* mysys_var; - void save() + Worker_thread_context() { psi_thread= PSI_CALL_get_thread(); mysys_var= my_thread_var; } - void restore() + ~Worker_thread_context() { PSI_CALL_set_thread(psi_thread); set_mysys_var(mysys_var); @@ -142,6 +142,44 @@ static inline void set_thd_idle(THD *thd) #endif } +/* + Per OS thread info (ID and pthread_self) + stored as TLS, because of syscall overhead + (on Linux) +*/ +struct OS_thread_info +{ + pthread_t self; + ssize_t stack_size; + uint32_t thread_id; + + inline bool initialized() { return stack_size != 0; } + + void init(ssize_t ssize) + { +#if _WIN32 + self= thread_id= GetCurrentThreadId(); +#else +#ifdef __NR_gettid + thread_id= (uint32) syscall(__NR_gettid); +#else + thread_id= 0; +#endif + self= pthread_self(); +#endif + stack_size= ssize; + } +}; +static thread_local OS_thread_info os_thread_info; + +static const OS_thread_info *get_os_thread_info() +{ + auto *res= &os_thread_info; + if (!res->initialized()) + res->init((ssize_t) (my_thread_stack_size * STACK_DIRECTION)); + return res; +} + /* Attach/associate the connection with the OS thread, */ @@ -154,7 +192,12 @@ static void thread_attach(THD* thd) #endif /* WITH_WSREP */ set_mysys_var(thd->mysys_var); thd->thread_stack=(char*)&thd; - thd->store_globals(); + set_current_thd(thd); + auto tinfo= get_os_thread_info(); + thd->real_id= tinfo->self; + thd->os_thread_id= tinfo->thread_id; + DBUG_ASSERT(thd->mysys_var == my_thread_var); + thd->mysys_var->stack_ends_here= thd->thread_stack + tinfo->stack_size; PSI_CALL_set_thread(thd->get_psi()); mysql_socket_set_thread_owner(thd->net.vio->mysql_socket); } @@ -179,7 +222,6 @@ void tp_callback(TP_connection *c) DBUG_ASSERT(c); Worker_thread_context worker_context; - worker_context.save(); THD *thd= c->thd; @@ -212,7 +254,6 @@ retry: thd->async_state.m_state = thd_async_state::enum_async_state::RESUMED; goto retry; } - worker_context.restore(); return; case DISPATCH_COMMAND_CLOSE_CONNECTION: /* QUIT or an error occurred. */ @@ -231,8 +272,6 @@ retry: c->state= TP_STATE_IDLE; if (c->start_io()) goto error; - - worker_context.restore(); return; error: @@ -242,7 +281,6 @@ error: threadpool_remove_connection(thd); } delete c; - worker_context.restore(); }