mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
MDEV-14482 - Cache line contention on ut_rnd_ulint_counter()
InnoDB RNG maintains global state, causing otherwise unnecessary bus traffic. Even worse this is cross-mutex traffic. That is different mutexes suffer from contention. Fixed delay of 4 was verified to give best throughput by OLTP update index and read-write benchmarks on Intel Broadwell (2/20/40) and ARM (1/46/46).
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
SET @start_global_value = @@global.innodb_spin_wait_delay;
|
||||
SELECT @start_global_value;
|
||||
@start_global_value
|
||||
6
|
||||
4
|
||||
Valid values are zero or above
|
||||
select @@global.innodb_spin_wait_delay >=0;
|
||||
@@global.innodb_spin_wait_delay >=0
|
||||
1
|
||||
select @@global.innodb_spin_wait_delay;
|
||||
@@global.innodb_spin_wait_delay
|
||||
6
|
||||
4
|
||||
select @@session.innodb_spin_wait_delay;
|
||||
ERROR HY000: Variable 'innodb_spin_wait_delay' is a GLOBAL variable
|
||||
show global variables like 'innodb_spin_wait_delay';
|
||||
Variable_name Value
|
||||
innodb_spin_wait_delay 6
|
||||
innodb_spin_wait_delay 4
|
||||
show session variables like 'innodb_spin_wait_delay';
|
||||
Variable_name Value
|
||||
innodb_spin_wait_delay 6
|
||||
innodb_spin_wait_delay 4
|
||||
select * from information_schema.global_variables where variable_name='innodb_spin_wait_delay';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_SPIN_WAIT_DELAY 6
|
||||
INNODB_SPIN_WAIT_DELAY 4
|
||||
select * from information_schema.session_variables where variable_name='innodb_spin_wait_delay';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_SPIN_WAIT_DELAY 6
|
||||
INNODB_SPIN_WAIT_DELAY 4
|
||||
set global innodb_spin_wait_delay=10;
|
||||
select @@global.innodb_spin_wait_delay;
|
||||
@@global.innodb_spin_wait_delay
|
||||
@@ -38,7 +38,7 @@ ERROR HY000: Variable 'innodb_spin_wait_delay' is a GLOBAL variable and should b
|
||||
set global innodb_spin_wait_delay=DEFAULT;
|
||||
select @@global.innodb_spin_wait_delay;
|
||||
@@global.innodb_spin_wait_delay
|
||||
6
|
||||
4
|
||||
set global innodb_spin_wait_delay=0;
|
||||
select @@global.innodb_spin_wait_delay;
|
||||
@@global.innodb_spin_wait_delay
|
||||
@@ -111,4 +111,4 @@ INNODB_SPIN_WAIT_DELAY 0
|
||||
SET @@global.innodb_spin_wait_delay = @start_global_value;
|
||||
SELECT @@global.innodb_spin_wait_delay;
|
||||
@@global.innodb_spin_wait_delay
|
||||
6
|
||||
4
|
||||
|
||||
@@ -1996,12 +1996,12 @@ READ_ONLY YES
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME INNODB_SPIN_WAIT_DELAY
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE 6
|
||||
GLOBAL_VALUE 4
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 6
|
||||
DEFAULT_VALUE 4
|
||||
VARIABLE_SCOPE GLOBAL
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT Maximum delay between polling for a spin lock (6 by default)
|
||||
VARIABLE_COMMENT Maximum delay between polling for a spin lock (4 by default)
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 6000
|
||||
NUMERIC_BLOCK_SIZE 0
|
||||
|
||||
@@ -1758,11 +1758,8 @@ dict_stats_analyze_index_for_n_prefix(
|
||||
ut_a(left <= right);
|
||||
ut_a(right <= last_idx_on_level);
|
||||
|
||||
/* we do not pass (left, right) because we do not want to ask
|
||||
ut_rnd_interval() to work with too big numbers since
|
||||
ib_uint64_t could be bigger than ulint */
|
||||
const ulint rnd = ut_rnd_interval(
|
||||
0, static_cast<ulint>(right - left));
|
||||
const ulint rnd = right == left ? 0 :
|
||||
ut_rnd_gen_ulint() % (right - left);
|
||||
|
||||
const ib_uint64_t dive_below_idx
|
||||
= boundaries->at(static_cast<unsigned>(left + rnd));
|
||||
|
||||
@@ -5978,17 +5978,6 @@ fil_tablespace_iterate(
|
||||
innodb_data_file_key, filepath,
|
||||
OS_FILE_OPEN, OS_FILE_READ_WRITE, srv_read_only_mode, &success);
|
||||
|
||||
DBUG_EXECUTE_IF("fil_tablespace_iterate_failure",
|
||||
{
|
||||
static bool once;
|
||||
|
||||
if (!once || ut_rnd_interval(0, 10) == 5) {
|
||||
once = true;
|
||||
success = false;
|
||||
os_file_close(file);
|
||||
}
|
||||
});
|
||||
|
||||
if (!success) {
|
||||
/* The following call prints an error message */
|
||||
os_file_get_last_error(true);
|
||||
|
||||
@@ -20559,8 +20559,8 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
|
||||
|
||||
static MYSQL_SYSVAR_UINT(spin_wait_delay, srv_spin_wait_delay,
|
||||
PLUGIN_VAR_OPCMDARG,
|
||||
"Maximum delay between polling for a spin lock (6 by default)",
|
||||
NULL, NULL, 6, 0, 6000, 0);
|
||||
"Maximum delay between polling for a spin lock (4 by default)",
|
||||
NULL, NULL, 4, 0, 6000, 0);
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
|
||||
@@ -225,7 +225,7 @@ struct TTASFutexMutex {
|
||||
return;
|
||||
}
|
||||
|
||||
ut_delay(ut_rnd_interval(0, max_delay));
|
||||
ut_delay(max_delay);
|
||||
}
|
||||
|
||||
for (n_waits= 0;; n_waits++) {
|
||||
@@ -362,7 +362,7 @@ struct TTASMutex {
|
||||
uint32_t n_spins = 0;
|
||||
|
||||
while (!try_lock()) {
|
||||
ut_delay(ut_rnd_interval(0, max_delay));
|
||||
ut_delay(max_delay);
|
||||
if (++n_spins == max_spins) {
|
||||
os_thread_yield();
|
||||
max_spins+= step;
|
||||
@@ -516,7 +516,7 @@ struct TTASEventMutex {
|
||||
sync_array_wait_event(sync_arr, cell);
|
||||
}
|
||||
} else {
|
||||
ut_delay(ut_rnd_interval(0, max_delay));
|
||||
ut_delay(max_delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,16 +61,6 @@ UNIV_INLINE
|
||||
ulint
|
||||
ut_rnd_gen_ulint(void);
|
||||
/*==================*/
|
||||
/********************************************************//**
|
||||
Generates a random integer from a given interval.
|
||||
@return the 'random' number */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ut_rnd_interval(
|
||||
/*============*/
|
||||
ulint low, /*!< in: low limit; can generate also this value */
|
||||
ulint high); /*!< in: high limit; can generate also this value */
|
||||
|
||||
/*******************************************************//**
|
||||
The following function generates a hash value for a ulint integer
|
||||
to a hash table of size table_size, which should be a prime or some
|
||||
|
||||
@@ -97,30 +97,6 @@ ut_rnd_gen_ulint(void)
|
||||
return(rnd);
|
||||
}
|
||||
|
||||
/********************************************************//**
|
||||
Generates a random integer from a given interval.
|
||||
@return the 'random' number */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
ut_rnd_interval(
|
||||
/*============*/
|
||||
ulint low, /*!< in: low limit; can generate also this value */
|
||||
ulint high) /*!< in: high limit; can generate also this value */
|
||||
{
|
||||
ulint rnd;
|
||||
|
||||
ut_ad(high >= low);
|
||||
|
||||
if (low == high) {
|
||||
|
||||
return(low);
|
||||
}
|
||||
|
||||
rnd = ut_rnd_gen_ulint();
|
||||
|
||||
return(low + (rnd % (high - low)));
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
The following function generates a hash value for a ulint integer
|
||||
to a hash table of size table_size, which should be a prime
|
||||
|
||||
@@ -7285,7 +7285,7 @@ lock_trx_release_locks(
|
||||
|
||||
/** Doing an implicit to explicit conversion
|
||||
should not be expensive. */
|
||||
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
|
||||
ut_delay(srv_spin_wait_delay);
|
||||
}
|
||||
|
||||
lock_mutex_enter();
|
||||
|
||||
@@ -317,10 +317,7 @@ lock_loop:
|
||||
while (i < srv_n_spin_wait_rounds &&
|
||||
my_atomic_load32_explicit(&lock->lock_word,
|
||||
MY_MEMORY_ORDER_RELAXED) <= 0) {
|
||||
if (srv_spin_wait_delay) {
|
||||
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
|
||||
}
|
||||
|
||||
ut_delay(srv_spin_wait_delay);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -441,9 +438,7 @@ rw_lock_x_lock_wait_func(
|
||||
|
||||
HMT_low();
|
||||
while (my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) < threshold) {
|
||||
if (srv_spin_wait_delay) {
|
||||
ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
|
||||
}
|
||||
ut_delay(srv_spin_wait_delay);
|
||||
|
||||
if (i < srv_n_spin_wait_rounds) {
|
||||
i++;
|
||||
@@ -714,12 +709,7 @@ lock_loop:
|
||||
HMT_low();
|
||||
while (i < srv_n_spin_wait_rounds
|
||||
&& my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) <= X_LOCK_HALF_DECR) {
|
||||
|
||||
if (srv_spin_wait_delay) {
|
||||
ut_delay(ut_rnd_interval(
|
||||
0, srv_spin_wait_delay));
|
||||
}
|
||||
|
||||
ut_delay(srv_spin_wait_delay);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -820,12 +810,7 @@ lock_loop:
|
||||
/* Spin waiting for the lock_word to become free */
|
||||
while (i < srv_n_spin_wait_rounds
|
||||
&& my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) <= X_LOCK_HALF_DECR) {
|
||||
|
||||
if (srv_spin_wait_delay) {
|
||||
ut_delay(ut_rnd_interval(
|
||||
0, srv_spin_wait_delay));
|
||||
}
|
||||
|
||||
ut_delay(srv_spin_wait_delay);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user