Commit 5d615366 authored by Mikael Ronstrom's avatar Mikael Ronstrom

Introduced a new timer based innodb thread concurrency. A new

parameter innodb_thread_concurrency_timer_based is used to
get this new feature (it is set by default). The new feature
is only available on platforms where atomic instructions are
available.
parent aefc0aca
...@@ -148,6 +148,9 @@ long innobase_max_merged_io = 64; ...@@ -148,6 +148,9 @@ long innobase_max_merged_io = 64;
/* Number of background IO threads for read and write. */ /* Number of background IO threads for read and write. */
long innobase_read_io_threads, innobase_write_io_threads; long innobase_read_io_threads, innobase_write_io_threads;
/* Use timer based InnoDB concurrency throttling flag */
static my_bool innobase_thread_concurrency_timer_based;
/* The following counter is used to convey information to InnoDB /* The following counter is used to convey information to InnoDB
about server activity: in selects it is not sensible to call about server activity: in selects it is not sensible to call
srv_active_wake_master_thread after each fetch or search, we only do srv_active_wake_master_thread after each fetch or search, we only do
...@@ -1602,6 +1605,9 @@ innobase_init( ...@@ -1602,6 +1605,9 @@ innobase_init(
srv_n_log_files = (ulint) innobase_log_files_in_group; srv_n_log_files = (ulint) innobase_log_files_in_group;
srv_log_file_size = (ulint) innobase_log_file_size; srv_log_file_size = (ulint) innobase_log_file_size;
srv_thread_concurrency_timer_based =
(ibool) innobase_thread_concurrency_timer_based;
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
srv_log_archive_on = (ulint) innobase_log_archive; srv_log_archive_on = (ulint) innobase_log_archive;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
...@@ -8236,6 +8242,12 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds, ...@@ -8236,6 +8242,12 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
"Count of spin-loop rounds in InnoDB mutexes", "Count of spin-loop rounds in InnoDB mutexes",
NULL, NULL, 20L, 0L, ~0L, 0); NULL, NULL, 20L, 0L, ~0L, 0);
static MYSQL_SYSVAR_BOOL(thread_concurrency_timer_based,
innobase_thread_concurrency_timer_based,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Use InnoDB timer based concurrency throttling. ",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
"Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.", "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
...@@ -8278,6 +8290,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { ...@@ -8278,6 +8290,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(read_io_threads), MYSQL_SYSVAR(read_io_threads),
MYSQL_SYSVAR(write_io_threads), MYSQL_SYSVAR(write_io_threads),
MYSQL_SYSVAR(max_merged_io), MYSQL_SYSVAR(max_merged_io),
MYSQL_SYSVAR(thread_concurrency_timer_based),
MYSQL_SYSVAR(file_per_table), MYSQL_SYSVAR(file_per_table),
MYSQL_SYSVAR(flush_log_at_trx_commit), MYSQL_SYSVAR(flush_log_at_trx_commit),
MYSQL_SYSVAR(flush_method), MYSQL_SYSVAR(flush_method),
......
...@@ -89,6 +89,8 @@ extern ulint srv_awe_window_size; ...@@ -89,6 +89,8 @@ extern ulint srv_awe_window_size;
extern ulint srv_mem_pool_size; extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size; extern ulint srv_lock_table_size;
extern ibool srv_thread_concurrency_timer_based;
extern ulint srv_n_file_io_threads; extern ulint srv_n_file_io_threads;
/* Number of background IO threads for read and write. Replaces /* Number of background IO threads for read and write. Replaces
* srv_n_file_io_threads. */ * srv_n_file_io_threads. */
......
...@@ -171,6 +171,7 @@ ulint srv_awe_window_size = 0; /* size in pages; MySQL inits ...@@ -171,6 +171,7 @@ ulint srv_awe_window_size = 0; /* size in pages; MySQL inits
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */ ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
ulint srv_lock_table_size = ULINT_MAX; ulint srv_lock_table_size = ULINT_MAX;
ulint srv_io_capacity = ULINT_MAX; /* Number of IO operations per ulint srv_io_capacity = ULINT_MAX; /* Number of IO operations per
second the server can do */ second the server can do */
...@@ -288,19 +289,20 @@ Value 10 should be good if there are less than 4 processors + 4 disks in the ...@@ -288,19 +289,20 @@ Value 10 should be good if there are less than 4 processors + 4 disks in the
computer. Bigger computers need bigger values. Value 0 will disable the computer. Bigger computers need bigger values. Value 0 will disable the
concurrency check. */ concurrency check. */
ibool srv_thread_concurrency_timer_based = TRUE;
ulong srv_thread_concurrency = 0; ulong srv_thread_concurrency = 0;
ulong srv_commit_concurrency = 0; ulong srv_commit_concurrency = 0;
os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data
structures */ structures */
lint srv_conc_n_threads = 0; /* number of OS threads currently lint srv_conc_n_threads = 0; /* number of OS threads currently
inside InnoDB; it is not an error inside InnoDB; it is not an error
if this drops temporarily below zero if this drops temporarily below zero
because we do not demand that every because we do not demand that every
thread increments this, but a thread thread increments this, but a thread
waiting for a lock decrements this waiting for a lock decrements this
temporarily */ temporarily */
ulint srv_conc_n_waiting_threads = 0; /* number of OS threads waiting in the ulint srv_conc_n_waiting_threads = 0; /* number of OS threads waiting in the
FIFO for a permission to enter InnoDB FIFO for a permission to enter InnoDB
*/ */
...@@ -1061,6 +1063,91 @@ ulong srv_max_purge_lag = 0; ...@@ -1061,6 +1063,91 @@ ulong srv_max_purge_lag = 0;
Puts an OS thread to wait if there are too many concurrent threads Puts an OS thread to wait if there are too many concurrent threads
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
static void
inc_srv_conc_n_threads(lint *n_threads)
{
*n_threads = os_atomic_increment(&srv_conc_n_threads, 1);
}
static void
dec_srv_conc_n_threads()
{
os_atomic_increment(&srv_conc_n_threads, -1);
}
static void
print_already_in_error(trx_t* trx)
{
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: trying to declare trx"
" to enter InnoDB, but\n"
"InnoDB: it already is declared.\n", stderr);
trx_print(stderr, trx, 0);
putc('\n', stderr);
return;
}
static void
enter_innodb_with_tickets(trx_t* trx)
{
trx->declared_to_be_inside_innodb = TRUE;
trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
return;
}
static void
srv_conc_enter_innodb_timer_based(trx_t* trx)
{
lint conc_n_threads;
ibool has_yielded = FALSE;
ulint has_slept = 0;
if (trx->declared_to_be_inside_innodb) {
print_already_in_error(trx);
}
retry:
if (srv_conc_n_threads < (lint) srv_thread_concurrency) {
inc_srv_conc_n_threads(&conc_n_threads);
if (conc_n_threads <= srv_thread_concurrency) {
enter_innodb_with_tickets(trx);
return;
}
dec_srv_conc_n_threads(&conc_n_threads);
}
if (!has_yielded)
{
has_yielded = TRUE;
os_thread_yield();
goto retry;
}
if (trx->has_search_latch
|| NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
inc_srv_conc_n_threads(&conc_n_threads);
enter_innodb_with_tickets(trx);
return;
}
if (has_slept < 2)
{
trx->op_info = "sleeping before entering InnoDB";
os_thread_sleep(10000);
trx->op_info = "";
has_slept++;
}
inc_srv_conc_n_threads(&conc_n_threads);
enter_innodb_with_tickets(trx);
return;
}
static void
srv_conc_exit_innodb_timer_based(trx_t* trx)
{
dec_srv_conc_n_threads();
trx->declared_to_be_inside_innodb = FALSE;
trx->n_tickets_to_enter_innodb = 0;
return;
}
void void
srv_conc_enter_innodb( srv_conc_enter_innodb(
/*==================*/ /*==================*/
...@@ -1091,15 +1178,17 @@ srv_conc_enter_innodb( ...@@ -1091,15 +1178,17 @@ srv_conc_enter_innodb(
return; return;
} }
#ifdef UNIV_SYNC_ATOMIC
if (srv_thread_concurrency_timer_based) {
srv_conc_enter_innodb_timer_based(trx);
return;
}
#endif
os_fast_mutex_lock(&srv_conc_mutex); os_fast_mutex_lock(&srv_conc_mutex);
retry: retry:
if (trx->declared_to_be_inside_innodb) { if (trx->declared_to_be_inside_innodb) {
ut_print_timestamp(stderr); print_already_in_error(trx);
fputs(" InnoDB: Error: trying to declare trx"
" to enter InnoDB, but\n"
"InnoDB: it already is declared.\n", stderr);
trx_print(stderr, trx, 0);
putc('\n', stderr);
os_fast_mutex_unlock(&srv_conc_mutex); os_fast_mutex_unlock(&srv_conc_mutex);
return; return;
...@@ -1226,17 +1315,25 @@ srv_conc_force_enter_innodb( ...@@ -1226,17 +1315,25 @@ srv_conc_force_enter_innodb(
trx_t* trx) /* in: transaction object associated with the trx_t* trx) /* in: transaction object associated with the
thread */ thread */
{ {
lint conc_n_threads;
if (UNIV_LIKELY(!srv_thread_concurrency)) { if (UNIV_LIKELY(!srv_thread_concurrency)) {
return; return;
} }
#ifdef UNIV_SYNC_ATOMIC
if (srv_thread_concurrency_timer_based) {
inc_srv_conc_n_threads(&conc_n_threads);
trx->declared_to_be_inside_innodb = TRUE;
trx->n_tickets_to_enter_innodb = 1;
return;
}
#endif
os_fast_mutex_lock(&srv_conc_mutex); os_fast_mutex_lock(&srv_conc_mutex);
srv_conc_n_threads++; srv_conc_n_threads++;
trx->declared_to_be_inside_innodb = TRUE; trx->declared_to_be_inside_innodb = TRUE;
trx->n_tickets_to_enter_innodb = 1; trx->n_tickets_to_enter_innodb = 1;
os_fast_mutex_unlock(&srv_conc_mutex); os_fast_mutex_unlock(&srv_conc_mutex);
} }
...@@ -1268,6 +1365,14 @@ srv_conc_force_exit_innodb( ...@@ -1268,6 +1365,14 @@ srv_conc_force_exit_innodb(
return; return;
} }
#ifdef UNIV_SYNC_ATOMIC
if (srv_thread_concurrency_timer_based)
{
srv_conc_exit_innodb_timer_based(trx);
return;
}
#endif
os_fast_mutex_lock(&srv_conc_mutex); os_fast_mutex_lock(&srv_conc_mutex);
srv_conc_n_threads--; srv_conc_n_threads--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment