Commit 41e6a154 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-14482 - Cache line contention on ut_rnd_interval()

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 is a backport of ce047900 from
MariaDB Server 10.3.
parent b1f2d3a8
SET @start_global_value = @@global.innodb_spin_wait_delay; SET @start_global_value = @@global.innodb_spin_wait_delay;
SELECT @start_global_value; SELECT @start_global_value;
@start_global_value @start_global_value
6 4
Valid values are zero or above Valid values are zero or above
select @@global.innodb_spin_wait_delay >=0; select @@global.innodb_spin_wait_delay >=0;
@@global.innodb_spin_wait_delay >=0 @@global.innodb_spin_wait_delay >=0
1 1
select @@global.innodb_spin_wait_delay; select @@global.innodb_spin_wait_delay;
@@global.innodb_spin_wait_delay @@global.innodb_spin_wait_delay
6 4
select @@session.innodb_spin_wait_delay; select @@session.innodb_spin_wait_delay;
ERROR HY000: Variable 'innodb_spin_wait_delay' is a GLOBAL variable ERROR HY000: Variable 'innodb_spin_wait_delay' is a GLOBAL variable
show global variables like 'innodb_spin_wait_delay'; show global variables like 'innodb_spin_wait_delay';
Variable_name Value Variable_name Value
innodb_spin_wait_delay 6 innodb_spin_wait_delay 4
show session variables like 'innodb_spin_wait_delay'; show session variables like 'innodb_spin_wait_delay';
Variable_name Value 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'; select * from information_schema.global_variables where variable_name='innodb_spin_wait_delay';
VARIABLE_NAME VARIABLE_VALUE 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'; select * from information_schema.session_variables where variable_name='innodb_spin_wait_delay';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
INNODB_SPIN_WAIT_DELAY 6 INNODB_SPIN_WAIT_DELAY 4
set global innodb_spin_wait_delay=10; set global innodb_spin_wait_delay=10;
select @@global.innodb_spin_wait_delay; select @@global.innodb_spin_wait_delay;
@@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 ...@@ -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; set global innodb_spin_wait_delay=DEFAULT;
select @@global.innodb_spin_wait_delay; select @@global.innodb_spin_wait_delay;
@@global.innodb_spin_wait_delay @@global.innodb_spin_wait_delay
6 4
set global innodb_spin_wait_delay=0; set global innodb_spin_wait_delay=0;
select @@global.innodb_spin_wait_delay; select @@global.innodb_spin_wait_delay;
@@global.innodb_spin_wait_delay @@global.innodb_spin_wait_delay
...@@ -111,4 +111,4 @@ INNODB_SPIN_WAIT_DELAY 0 ...@@ -111,4 +111,4 @@ INNODB_SPIN_WAIT_DELAY 0
SET @@global.innodb_spin_wait_delay = @start_global_value; SET @@global.innodb_spin_wait_delay = @start_global_value;
SELECT @@global.innodb_spin_wait_delay; SELECT @@global.innodb_spin_wait_delay;
@@global.innodb_spin_wait_delay @@global.innodb_spin_wait_delay
6 4
...@@ -2228,10 +2228,10 @@ READ_ONLY YES ...@@ -2228,10 +2228,10 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_SPIN_WAIT_DELAY VARIABLE_NAME INNODB_SPIN_WAIT_DELAY
SESSION_VALUE NULL SESSION_VALUE NULL
DEFAULT_VALUE 6 DEFAULT_VALUE 4
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED 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_MIN_VALUE 0
NUMERIC_MAX_VALUE 6000 NUMERIC_MAX_VALUE 6000
NUMERIC_BLOCK_SIZE 0 NUMERIC_BLOCK_SIZE 0
......
...@@ -20716,8 +20716,8 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds, ...@@ -20716,8 +20716,8 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
static MYSQL_SYSVAR_UINT(spin_wait_delay, srv_spin_wait_delay, static MYSQL_SYSVAR_UINT(spin_wait_delay, srv_spin_wait_delay,
PLUGIN_VAR_OPCMDARG, PLUGIN_VAR_OPCMDARG,
"Maximum delay between polling for a spin lock (6 by default)", "Maximum delay between polling for a spin lock (4 by default)",
NULL, NULL, 6, 0, 6000, 0); NULL, NULL, 4, 0, 6000, 0);
static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
......
...@@ -225,7 +225,7 @@ struct TTASFutexMutex { ...@@ -225,7 +225,7 @@ struct TTASFutexMutex {
return; return;
} }
ut_delay(ut_rnd_interval(max_delay)); ut_delay(max_delay);
} }
for (n_waits= 0;; n_waits++) { for (n_waits= 0;; n_waits++) {
...@@ -362,7 +362,7 @@ struct TTASMutex { ...@@ -362,7 +362,7 @@ struct TTASMutex {
uint32_t n_spins = 0; uint32_t n_spins = 0;
while (!try_lock()) { while (!try_lock()) {
ut_delay(ut_rnd_interval(max_delay)); ut_delay(max_delay);
if (++n_spins == max_spins) { if (++n_spins == max_spins) {
os_thread_yield(); os_thread_yield();
max_spins+= step; max_spins+= step;
...@@ -516,7 +516,7 @@ struct TTASEventMutex { ...@@ -516,7 +516,7 @@ struct TTASEventMutex {
sync_array_wait_event(sync_arr, cell); sync_array_wait_event(sync_arr, cell);
} }
} else { } else {
ut_delay(ut_rnd_interval(max_delay)); ut_delay(max_delay);
} }
} }
......
...@@ -298,10 +298,7 @@ rw_lock_s_lock_spin( ...@@ -298,10 +298,7 @@ rw_lock_s_lock_spin(
/* Spin waiting for the writer field to become free */ /* Spin waiting for the writer field to become free */
HMT_low(); HMT_low();
while (i < srv_n_spin_wait_rounds && lock->lock_word <= 0) { while (i < srv_n_spin_wait_rounds && lock->lock_word <= 0) {
if (srv_spin_wait_delay) { ut_delay(srv_spin_wait_delay);
ut_delay(ut_rnd_interval(srv_spin_wait_delay));
}
i++; i++;
} }
...@@ -420,13 +417,9 @@ rw_lock_x_lock_wait_func( ...@@ -420,13 +417,9 @@ rw_lock_x_lock_wait_func(
ut_ad(lock->lock_word <= threshold); ut_ad(lock->lock_word <= threshold);
HMT_low();
while (lock->lock_word < threshold) { while (lock->lock_word < threshold) {
ut_delay(srv_spin_wait_delay);
HMT_low();
if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(srv_spin_wait_delay));
}
if (i < srv_n_spin_wait_rounds) { if (i < srv_n_spin_wait_rounds) {
i++; i++;
...@@ -683,10 +676,7 @@ rw_lock_x_lock_func( ...@@ -683,10 +676,7 @@ rw_lock_x_lock_func(
while (i < srv_n_spin_wait_rounds while (i < srv_n_spin_wait_rounds
&& lock->lock_word <= X_LOCK_HALF_DECR) { && lock->lock_word <= X_LOCK_HALF_DECR) {
if (srv_spin_wait_delay) { ut_delay(srv_spin_wait_delay);
ut_delay(ut_rnd_interval(srv_spin_wait_delay));
}
i++; i++;
} }
...@@ -788,10 +778,7 @@ rw_lock_sx_lock_func( ...@@ -788,10 +778,7 @@ rw_lock_sx_lock_func(
while (i < srv_n_spin_wait_rounds while (i < srv_n_spin_wait_rounds
&& lock->lock_word <= X_LOCK_HALF_DECR) { && lock->lock_word <= X_LOCK_HALF_DECR) {
if (srv_spin_wait_delay) { ut_delay(srv_spin_wait_delay);
ut_delay(ut_rnd_interval(srv_spin_wait_delay));
}
i++; i++;
} }
......
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