summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-12-10 11:23:46 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-12-10 17:01:36 +0200
commit41e6a154ece1c7d49becac0ccaa72f507686d298 (patch)
treef4329da603e99b1f9576dd6eeec54ccf1a0d07e0
parentb1f2d3a8c8d9bd10e088111ca966b3f7be35df35 (diff)
downloadmariadb-git-41e6a154ece1c7d49becac0ccaa72f507686d298.tar.gz
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 ce0479006523bc72ed6abb703bd1f87ff256fd8a from MariaDB Server 10.3.
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result16
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result4
-rw-r--r--storage/innobase/handler/ha_innodb.cc4
-rw-r--r--storage/innobase/include/ib0mutex.h6
-rw-r--r--storage/innobase/sync/sync0rw.cc23
5 files changed, 20 insertions, 33 deletions
diff --git a/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result b/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result
index 88516a854fe..b76ba4933f2 100644
--- a/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result
@@ -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
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index 65d47347a15..4be85752cc7 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -2228,10 +2228,10 @@ READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_SPIN_WAIT_DELAY
SESSION_VALUE NULL
-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
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 7e61a38320a..1e1583804eb 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -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,
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,
diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h
index 6c04563b97a..a7289777e00 100644
--- a/storage/innobase/include/ib0mutex.h
+++ b/storage/innobase/include/ib0mutex.h
@@ -225,7 +225,7 @@ struct TTASFutexMutex {
return;
}
- ut_delay(ut_rnd_interval(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(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(max_delay));
+ ut_delay(max_delay);
}
}
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index c9b8a1e58a5..df710a53cf6 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -298,10 +298,7 @@ lock_loop:
/* Spin waiting for the writer field to become free */
HMT_low();
while (i < srv_n_spin_wait_rounds && lock->lock_word <= 0) {
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(srv_spin_wait_delay));
- }
-
+ ut_delay(srv_spin_wait_delay);
i++;
}
@@ -420,13 +417,9 @@ rw_lock_x_lock_wait_func(
ut_ad(lock->lock_word <= threshold);
+ HMT_low();
while (lock->lock_word < threshold) {
-
-
- HMT_low();
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(srv_spin_wait_delay));
- }
+ ut_delay(srv_spin_wait_delay);
if (i < srv_n_spin_wait_rounds) {
i++;
@@ -683,10 +676,7 @@ lock_loop:
while (i < srv_n_spin_wait_rounds
&& lock->lock_word <= X_LOCK_HALF_DECR) {
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(srv_spin_wait_delay));
- }
-
+ ut_delay(srv_spin_wait_delay);
i++;
}
@@ -788,10 +778,7 @@ lock_loop:
while (i < srv_n_spin_wait_rounds
&& lock->lock_word <= X_LOCK_HALF_DECR) {
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(srv_spin_wait_delay));
- }
-
+ ut_delay(srv_spin_wait_delay);
i++;
}