← Back to team overview

maria-developers team mailing list archive

Re: 3c6f17a130b: Allocate Session_sysvars_tracker statically

 

Hi, Sergey!

Please, see few questions below

On Mar 25, Sergey Vojtovich wrote:
> revision-id: 3c6f17a130b (mariadb-10.3.12-93-g3c6f17a130b)
> parent(s): db9854b7d48
> author: Sergey Vojtovich <svoj@xxxxxxxxxxx>
> committer: Sergey Vojtovich <svoj@xxxxxxxxxxx>
> timestamp: 2019-03-19 23:40:07 +0400
> message:
> 
> Allocate Session_sysvars_tracker statically
> 
> One less new/delete per connection.
> 
> Removed m_mem_flag since most allocs are thread specific. The only
> exception are allocs performed during initialization.
> 
> Removed State_tracker and Session_tracker constructors as they don't make
> sense anymore.
> 
> Rather than having session_tracker.deinit(), fixed memory accounting so
> that it gets initialized before any other constructor and deinitialized
> after all destructors done. Cons: makes THD a few pointers larger :(
> 
> Part of MDEV-14984 - regression in connect performance
> 
> diff --git a/sql/sql_class.h b/sql/sql_class.h
> index 69e6f58f854..64d772e5d17 100644
> --- a/sql/sql_class.h
> +++ b/sql/sql_class.h
> @@ -2145,13 +2145,34 @@ struct wait_for_commit
>  
>  extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
>  
> +
> +/**
> +  A wrapper around thread_count.
> +
> +  It must be specified as a first base class of THD, so that increment is
> +  done before any other THD constructors and decrement - after any other THD
> +  destructors.
> +
> +  Destructor unblocks close_conneciton() if there are no more THD's left.
> +*/
> +class THD_count
> +{
> +  THD *orig_thd;
> +  THD_count();
> +  ~THD_count();
> +  friend class THD;
> +};

1. Why a separate class, what's wrong with having it in THD? No
   downcasts, no risk that someone would try to use it separately.

2. orig_thd looks very suspicious. You preserve the old THD* pointer for
   the whole duration of this THD lifetime and restore it at the end.
   How can you know that the "orig_thd" is still valid? Why do you need
   to do it anyway?

> +
> +
>  /**
>    @class THD
>    For each client connection we create a separate thread with THD serving as
>    a thread/connection descriptor
>  */
>  
> -class THD :public Statement,
> +class THD: public THD_count, /* this must be first */

an assert would be better than "/* must be first */".
Like, assert(&orig_thd == this) or something.

> +           public Statement,
> +
>             /*
>               This is to track items changed during execution of a prepared
>               statement/stored procedure. It's created by
> @@ -2176,19 +2197,6 @@ class THD :public Statement,
>    inline bool is_conventional() const
>    { DBUG_ASSERT(0); return Statement::is_conventional(); }
>  
> -  void dec_thread_count(void)
> -  {
> -    DBUG_ASSERT(thread_count > 0);
> -    thread_safe_decrement32(&thread_count);
> -    signal_thd_deleted();
> -  }
> -
> -
> -  void inc_thread_count(void)
> -  {
> -    thread_safe_increment32(&thread_count);
> -  }
> -
>  public:
>    MDL_context mdl_context;
>  
> diff --git a/sql/sql_class.cc b/sql/sql_class.cc
> index 9c9fa228e2a..afe4123a52c 100644
> --- a/sql/sql_class.cc
> +++ b/sql/sql_class.cc
> @@ -597,8 +597,46 @@ extern "C" void thd_kill_timeout(THD* thd)
>    thd->awake(KILL_TIMEOUT);
>  }
>  
> -THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
> -  :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
> +
> +THD_count::THD_count()
> +{
> +  THD *thd= static_cast<THD*>(this);
> +  thread_safe_increment32(&thread_count);
> +  /*
> +    We set THR_THD to temporally point to this THD to register all the
> +    variables that allocates memory for this THD
> +  */
> +  orig_thd= current_thd;
> +  set_current_thd(thd);
> +  thd->status_var.local_memory_used= sizeof(THD);
> +  thd->status_var.max_local_memory_used= thd->status_var.local_memory_used;
> +  thd->status_var.global_memory_used= 0;
> +  thd->variables.max_mem_used= global_system_variables.max_mem_used;
> +}
> +
> +
> +THD_count::~THD_count()
> +{
> +  THD *thd= static_cast<THD*>(this);
> +  if (thd->status_var.local_memory_used != 0)
> +  {
> +    DBUG_PRINT("error", ("memory_used: %lld",
> +                         thd->status_var.local_memory_used));
> +    SAFEMALLOC_REPORT_MEMORY(thd->thread_id);
> +    DBUG_ASSERT(thd->status_var.local_memory_used == 0 ||
> +                !debug_assert_on_not_freed_memory);
> +  }
> +  update_global_memory_status(thd->status_var.global_memory_used);
> +  set_current_thd(orig_thd);
> +  DBUG_ASSERT(thread_count > 0);
> +  thread_safe_decrement32(&thread_count);
> +  signal_thd_deleted();
> +}
> +
> +
> +THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock):
> +   THD_count(),
> +   Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
>               /* statement id */ 0),
>     rli_fake(0), rgi_fake(0), rgi_slave(NULL),
>     protocol_text(this), protocol_binary(this),
> @@ -654,15 +692,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
>    ulong tmp;
>    bzero(&variables, sizeof(variables));
>  
> -  /*
> -    We set THR_THD to temporally point to this THD to register all the
> -    variables that allocates memory for this THD
> -  */
> -  THD *old_THR_THD= current_thd;
> -  set_current_thd(this);
> -  status_var.local_memory_used= sizeof(THD);
> -  status_var.max_local_memory_used= status_var.local_memory_used;
> -  status_var.global_memory_used= 0;
>    variables.pseudo_thread_id= thread_id;
>    variables.max_mem_used= global_system_variables.max_mem_used;
>    main_da.init();
> @@ -849,8 +878,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
>    save_prep_leaf_list= FALSE;
>    org_charset= 0;
>    /* Restore THR_THD */
> -  set_current_thd(old_THR_THD);
> -  inc_thread_count();
> +  set_current_thd(orig_thd);
>  }
>  
>  
> @@ -1589,7 +1617,6 @@ void THD::reset_for_reuse()
>  
>  THD::~THD()
>  {
> -  THD *orig_thd= current_thd;
>    THD_CHECK_SENTRY(this);
>    DBUG_ENTER("~THD()");
>    /* Check that we have already called thd->unlink() */
> @@ -1601,7 +1628,11 @@ THD::~THD()
>      In error cases, thd may not be current thd. We have to fix this so
>      that memory allocation counting is done correctly
>    */
> -  set_current_thd(this);
> +  orig_thd= current_thd;
> +  if (orig_thd == this)
> +    orig_thd= 0;
> +  else
> +    set_current_thd(this);
>    if (!status_in_global)
>      add_status_to_global();
>  
> @@ -1655,22 +1686,6 @@ THD::~THD()
>      lf_hash_put_pins(xid_hash_pins);
>    /* Ensure everything is freed */
>    status_var.local_memory_used-= sizeof(THD);
> -
> -  /* trick to make happy memory accounting system */
> -#ifndef EMBEDDED_LIBRARY
> -  session_tracker.deinit();
> -#endif //EMBEDDED_LIBRARY
> -
> -  if (status_var.local_memory_used != 0)
> -  {
> -    DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used));
> -    SAFEMALLOC_REPORT_MEMORY(thread_id);
> -    DBUG_ASSERT(status_var.local_memory_used == 0 ||
> -                !debug_assert_on_not_freed_memory);
> -  }
> -  update_global_memory_status(status_var.global_memory_used);
> -  set_current_thd(orig_thd == this ? 0 : orig_thd);
> -  dec_thread_count();
>    DBUG_VOID_RETURN;
>  }

Regards,
Sergei
Chief Architect MariaDB
and security@xxxxxxxxxxx