diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-10 11:23:46 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-12-10 17:01:36 +0200 |
commit | 41e6a154ece1c7d49becac0ccaa72f507686d298 (patch) | |
tree | f4329da603e99b1f9576dd6eeec54ccf1a0d07e0 | |
parent | b1f2d3a8c8d9bd10e088111ca966b3f7be35df35 (diff) | |
download | mariadb-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.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/sys_vars/r/sysvars_innodb.result | 4 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 4 | ||||
-rw-r--r-- | storage/innobase/include/ib0mutex.h | 6 | ||||
-rw-r--r-- | storage/innobase/sync/sync0rw.cc | 23 |
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++; } |