Remove reader optimistic spinning
cover Remove reader optimistic spinning
This patch series is to remove reader optimistic spinning in kernel 5.10 to improve the MongoDB performance. Performance measurements (10 times running average of overall throughput ops/sec) are using MongoDB 5.0.11 and YCSB [1] microbenchmark with workloadA [2] on AWS EC2 m5.4xlarge/m6g.4xlarge (16-vCPU 64GiB-memory) instances with a 512GB EBS IO1 drive disk with 5000 IOPS and separating MongoDB and YCSB load generator on 2 instances and setting recordcount=25000000 and operationcount=10000000 to see the impacts of these changes:
Before - v5.10.165 kernel in OS Amazon Linux 2
After - v5.10.165 kernel with reader spinning disabled in OS Amazon Linux 2
| Arch | Instance Type | Before | After | |---------+---------------+---------+---------| | x86_64 | m5.4xlarge | 37365.4 | 42373.9 | |---------+---------------+---------+---------| | aarch64 | m6g.4xlarge | 33823.1 | 43113.7 | |---------+---------------+---------+---------|
It can be seen that the MongoDB throughput can be improved around 13% in x86_64 and 27% in aarch64 after disabling reader optimistic spinning and these patches can be applied to 5.10 with no conflict so we wonder if it's possible to backport them to stable 5.10?
[1] https://github.com/brianfrankcooper/YCSB/releases/download/0.17.0/ycsb-0.17.0.tar.gz
[2] https://github.com/brianfrankcooper/YCSB/blob/master/workloads/workloada
Thanks,
Shaoying
Peter Zijlstra (3):
locking/rwsem: Better collate rwsem_read_trylock() locking/rwsem: Introduce rwsem_write_trylock() locking/rwsem: Fold __down_{read,write}*()
Waiman Long (4):
locking/rwsem: Pass the current atomic count to
rwsem_down_read_slowpath()
locking/rwsem: Prevent potential lock starvation locking/rwsem: Enable reader optimistic lock stealing locking/rwsem: Remove reader optimistic spinning
kernel/locking/lock_events_list.h | 6 +- kernel/locking/rwsem.c | 359 +++++++++--------------------- 2 files changed, 106 insertions(+), 259 deletions(-)
Signature · 1 line
2.38.1
PATCH 1/7 locking/rwsem: Better collate rwsem_read_trylock()
From: Peter Zijlstra <[email protected]>
commit 3379116a0ca965b00e6522c7ea3f16c9dbd8f9f9 upstream
All users of rwsem_read_trylock() do rwsem_set_reader_owned(sem) on success, move it into rwsem_read_trylock() proper.
--- kernel/locking/rwsem.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
kernel/locking/rwsem.c +8 -7
@@ -273,9 +273,16 @@ static inline void rwsem_set_nonspinnable(struct rw_semaphore *sem)static inline bool rwsem_read_trylock (struct rw_semaphore *sem) {long cnt =atomic_long_add_return_acquire (RWSEM_READER_BIAS , &sem->count); +if (WARN_ON_ONCE (cnt <0 ))rwsem_set_nonspinnable (sem); -return !(cnt &RWSEM_READ_FAILED_MASK ); + +if (!(cnt &RWSEM_READ_FAILED_MASK )) { +rwsem_set_reader_owned (sem); +return true; + } + +return false; }/*
@@ -1340,8 +1347,6 @@ static inline void __down_read(struct rw_semaphore *sem)if (!rwsem_read_trylock (sem)) {rwsem_down_read_slowpath (sem,TASK_UNINTERRUPTIBLE );DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); - }else { -rwsem_set_reader_owned (sem); } }
@@ -1351,8 +1356,6 @@ static inline int __down_read_interruptible(struct rw_semaphore *sem)if (IS_ERR (rwsem_down_read_slowpath (sem,TASK_INTERRUPTIBLE )))return -EINTR ;DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); - }else { -rwsem_set_reader_owned (sem); }return 0 ; }
@@ -1363,8 +1366,6 @@ static inline int __down_read_killable(struct rw_semaphore *sem)if (IS_ERR (rwsem_down_read_slowpath (sem,TASK_KILLABLE )))return -EINTR ;DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); - }else { -rwsem_set_reader_owned (sem); }return 0 ; }
Signature · 1 line
2.38.1
PATCH 2/7 locking/rwsem: Introduce rwsem_write_trylock()
In reply to Shaoying XuFrom: Peter Zijlstra <[email protected]>
commit 285c61aedf6bc5d81b37e4dc48c19012e8ff9836 upstream
One copy of this logic is better than three.
--- kernel/locking/rwsem.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-)
kernel/locking/rwsem.c +16 -22
@@ -285,6 +285,18 @@ static inline bool rwsem_read_trylock(struct rw_semaphore *sem)return false; } +static inline bool rwsem_write_trylock (struct rw_semaphore *sem) +{ +long tmp =RWSEM_UNLOCKED_VALUE ; + +if (atomic_long_try_cmpxchg_acquire (&sem->count, &tmp,RWSEM_WRITER_LOCKED )) { +rwsem_set_owner (sem); +return true; + } + +return false; +} +/* * Return just the real task structure pointer of the owner */
@@ -1395,42 +1407,24 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)*/ static inline void __down_write (struct rw_semaphore *sem) { -long tmp =RWSEM_UNLOCKED_VALUE ; - -if (unlikely (!atomic_long_try_cmpxchg_acquire (&sem->count, &tmp, -RWSEM_WRITER_LOCKED ))) +if (unlikely (!rwsem_write_trylock (sem)))rwsem_down_write_slowpath (sem,TASK_UNINTERRUPTIBLE ); -else -rwsem_set_owner (sem); }static inline int __down_write_killable (struct rw_semaphore *sem) { -long tmp =RWSEM_UNLOCKED_VALUE ; - -if (unlikely (!atomic_long_try_cmpxchg_acquire (&sem->count, &tmp, -RWSEM_WRITER_LOCKED ))) { +if (unlikely (!rwsem_write_trylock (sem))) {if (IS_ERR (rwsem_down_write_slowpath (sem,TASK_KILLABLE )))return -EINTR ; - }else { -rwsem_set_owner (sem); } +return 0 ; }static inline int __down_write_trylock (struct rw_semaphore *sem) { -long tmp; -DEBUG_RWSEMS_WARN_ON (sem->magic != sem, sem); - - tmp =RWSEM_UNLOCKED_VALUE ; -if (atomic_long_try_cmpxchg_acquire (&sem->count, &tmp, -RWSEM_WRITER_LOCKED )) { -rwsem_set_owner (sem); -return true; - } -return false; +return rwsem_write_trylock (sem); }/*
Signature · 1 line
2.38.1
PATCH 3/7 locking/rwsem: Fold __down_{read,write}*()
In reply to Shaoying XuFrom: Peter Zijlstra <[email protected]>
commit c995e638ccbbc65a76d1713c4fdcf927e7e2cb83 upstream
There's a lot needless duplication in __down_{read,write}*(), cure that with a helper.
--- kernel/locking/rwsem.c | 45 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-)
kernel/locking/rwsem.c +23 -22
@@ -1354,32 +1354,29 @@ static struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)/* * lock for reading */ -static inline void __down_read (struct rw_semaphore *sem) +static inline int __down_read_common (struct rw_semaphore *sem,int state) {if (!rwsem_read_trylock (sem)) { -rwsem_down_read_slowpath (sem,TASK_UNINTERRUPTIBLE ); +if (IS_ERR (rwsem_down_read_slowpath (sem, state))) +return -EINTR ;DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); } +return 0 ; +} + +static inline void __down_read (struct rw_semaphore *sem) +{ +__down_read_common (sem,TASK_UNINTERRUPTIBLE ); }static inline int __down_read_interruptible (struct rw_semaphore *sem) { -if (!rwsem_read_trylock (sem)) { -if (IS_ERR (rwsem_down_read_slowpath (sem,TASK_INTERRUPTIBLE ))) -return -EINTR ; -DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); - } -return 0 ; +return __down_read_common (sem,TASK_INTERRUPTIBLE ); }static inline int __down_read_killable (struct rw_semaphore *sem) { -if (!rwsem_read_trylock (sem)) { -if (IS_ERR (rwsem_down_read_slowpath (sem,TASK_KILLABLE ))) -return -EINTR ; -DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); - } -return 0 ; +return __down_read_common (sem,TASK_KILLABLE ); }static inline int __down_read_trylock (struct rw_semaphore *sem)
@@ -1405,22 +1402,26 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)/* * lock for writing */ -static inline void __down_write (struct rw_semaphore *sem) -{ -if (unlikely (!rwsem_write_trylock (sem))) -rwsem_down_write_slowpath (sem,TASK_UNINTERRUPTIBLE ); -} - -static inline int __down_write_killable (struct rw_semaphore *sem) +static inline int __down_write_common (struct rw_semaphore *sem,int state) {if (unlikely (!rwsem_write_trylock (sem))) { -if (IS_ERR (rwsem_down_write_slowpath (sem,TASK_KILLABLE ))) +if (IS_ERR (rwsem_down_write_slowpath (sem, state)))return -EINTR ; }return 0 ; } +static inline void __down_write (struct rw_semaphore *sem) +{ +__down_write_common (sem,TASK_UNINTERRUPTIBLE ); +} + +static inline int __down_write_killable (struct rw_semaphore *sem) +{ +return __down_write_common (sem,TASK_KILLABLE ); +} +static inline int __down_write_trylock (struct rw_semaphore *sem) {DEBUG_RWSEMS_WARN_ON (sem->magic != sem, sem);
Signature · 1 line
2.38.1
PATCH 4/7 locking/rwsem: Pass the current atomic count to rwsem_down_read_slowpath()
In reply to Shaoying XuFrom: Waiman Long <[email protected]>
commit c8fe8b0564388f41147326f31e4587171aacccd4 upstream
The atomic count value right after reader count increment can be useful to determine the rwsem state at trylock time. So the count value is passed down to rwsem_down_read_slowpath() to be used when appropriate.
--- kernel/locking/rwsem.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
kernel/locking/rwsem.c +10 -8
@@ -270,14 +270,14 @@ static inline void rwsem_set_nonspinnable(struct rw_semaphore *sem) owner | RWSEM_NONSPINNABLE)); } -static inline bool rwsem_read_trylock (struct rw_semaphore *sem) +static inline bool rwsem_read_trylock (struct rw_semaphore *sem,long *cntp) { -long cnt =atomic_long_add_return_acquire (RWSEM_READER_BIAS , &sem->count); + *cntp =atomic_long_add_return_acquire (RWSEM_READER_BIAS , &sem->count); -if (WARN_ON_ONCE (cnt <0 )) +if (WARN_ON_ONCE (*cntp <0 ))rwsem_set_nonspinnable (sem); -if (!(cnt &RWSEM_READ_FAILED_MASK )) { +if (!(*cntp &RWSEM_READ_FAILED_MASK )) {rwsem_set_reader_owned (sem);return true; }
@@ -1008,9 +1008,9 @@ rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long nonspinnable)* Wait for the read lock to be granted */ static struct rw_semaphore __sched * -rwsem_down_read_slowpath (struct rw_semaphore *sem,int state) +rwsem_down_read_slowpath (struct rw_semaphore *sem,long count,int state) { -long count, adjustment = -RWSEM_READER_BIAS ; +long adjustment = -RWSEM_READER_BIAS ;struct rwsem_waiter waiter;DEFINE_WAKE_Q (wake_q);bool wake = false;
@@ -1356,8 +1356,10 @@ static struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)*/ static inline int __down_read_common (struct rw_semaphore *sem,int state) { -if (!rwsem_read_trylock (sem)) { -if (IS_ERR (rwsem_down_read_slowpath (sem, state))) +long count; + +if (!rwsem_read_trylock (sem, &count)) { +if (IS_ERR (rwsem_down_read_slowpath (sem, count, state)))return -EINTR ;DEBUG_RWSEMS_WARN_ON (!is_rwsem_reader_owned (sem), sem); }
Signature · 1 line
2.38.1
PATCH 5/7 locking/rwsem: Prevent potential lock starvation
In reply to Shaoying XuFrom: Waiman Long <[email protected]>
commit 2f06f702925b512a95b95dca3855549c047eef58 upstream
The lock handoff bit is added in commit 4f23dbc1e657 ("locking/rwsem:
Implement lock handoff to prevent lock starvation") to avoid lock starvation. However, allowing readers to do optimistic spinning does introduce an unlikely scenario where lock starvation can happen.
The lock handoff bit may only be set when a waiter is being woken up. In the case of reader unlock, wakeup happens only when the reader count reaches 0. If there is a continuous stream of incoming readers acquiring read lock via optimistic spinning, it is possible that the reader count may never reach 0 and so the handoff bit will never be asserted.
One way to prevent this scenario from happening is to disallow optimistic spinning if the rwsem is currently owned by readers. If the previous or current owner is a writer, optimistic spinning will be allowed.
If the previous owner is a reader but the reader count has reached 0 before, a wakeup should have been issued. So the handoff mechanism will be kicked in to prevent lock starvation. As a result, it should be OK to do optimistic spinning in this case.
This patch may have some impact on reader performance as it reduces reader optimistic spinning especially if the lock critical sections are short the number of contending readers are small.
--- kernel/locking/rwsem.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
kernel/locking/rwsem.c +13 -2
@@ -1010,16 +1010,27 @@ rwsem_spin_on_owner(struct rw_semaphore *sem, unsigned long nonspinnable) static struct rw_semaphore __sched *rwsem_down_read_slowpath (struct rw_semaphore *sem,long count,int state) { -long adjustment = -RWSEM_READER_BIAS ; +long owner, adjustment = -RWSEM_READER_BIAS ; +long rcnt = (count >>RWSEM_READER_SHIFT );struct rwsem_waiter waiter;DEFINE_WAKE_Q (wake_q);bool wake = false; +/* +* To prevent a constant stream of readers from starving a sleeping +* waiter, don't attempt optimistic spinning if the lock is currently +* owned by readers. +*/ + owner =atomic_long_read (&sem->owner); +if ((owner &RWSEM_READER_OWNED ) && (rcnt >1 ) && + !(count &RWSEM_WRITER_LOCKED )) + goto queue; +/* * Save the current read-owner of rwsem, if available, and the * reader nonspinnable bit. */ - waiter.last_rowner =atomic_long_read (&sem->owner); + waiter.last_rowner = owner;if (!(waiter.last_rowner &RWSEM_READER_OWNED )) waiter.last_rowner &=RWSEM_RD_NONSPINNABLE ;
Signature · 1 line
2.38.1
PATCH 6/7 locking/rwsem: Enable reader optimistic lock stealing
From: Waiman Long <[email protected]>
commit 1a728dff855a318bb58bcc1259b1826a7ad9f0bd upstream
If the optimistic spinning queue is empty and the rwsem does not have the handoff or write-lock bits set, it is actually not necessary to call rwsem_optimistic_spin() to spin on it. Instead, it can steal the lock directly as its reader bias is in the count already. If it is the first reader in this state, it will try to wake up other readers in the wait queue.
With this patch applied, the following were the lock event counts after rebooting a 2-socket system and a "make -j96" kernel rebuild.
rwsem_opt_rlock=4437
rwsem_rlock=29
rwsem_rlock_steal=19
So lock stealing represents about 0.4% of all the read locks acquired in the slow path.
--- kernel/locking/lock_events_list.h | 1 + kernel/locking/rwsem.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+)
kernel/locking/lock_events_list.h +1 -0
@@ -63,6 +63,7 @@ LOCK_EVENT(rwsem_opt_nospin) /* # of disabled optspins */ LOCK_EVENT(rwsem_opt_norspin) /* # of disabled reader-only optspins */ LOCK_EVENT(rwsem_opt_rlock2) /* # of opt-acquired 2ndary read locks */ LOCK_EVENT(rwsem_rlock) /* # of read locks acquired */ +LOCK_EVENT(rwsem_rlock_steal) /* # of read locks by lock stealing */ LOCK_EVENT(rwsem_rlock_fast) /* # of fast read locks acquired */ LOCK_EVENT(rwsem_rlock_fail) /* # of failed read lock acquisitions */ LOCK_EVENT(rwsem_rlock_handoff) /* # of read lock handoffs */
kernel/locking/rwsem.c +28 -0
@@ -976,6 +976,12 @@ static inline bool rwsem_reader_phase_trylock(struct rw_semaphore *sem, }return false; } + +static inline bool rwsem_no_spinners (struct rw_semaphore *sem) +{ +return !osq_is_locked (&sem->osq); +} +#else static inline bool rwsem_can_spin_on_owner (struct rw_semaphore *sem,unsigned long nonspinnable)
@@ -996,6 +1002,11 @@ static inline bool rwsem_reader_phase_trylock(struct rw_semaphore *sem,return false; } +static inline bool rwsem_no_spinners (sem ) +{ +return false; +} +static inline int rwsem_spin_on_owner (struct rw_semaphore *sem,unsigned long nonspinnable) {
@@ -1026,6 +1037,22 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, long count, int state) !(count & RWSEM_WRITER_LOCKED)) goto queue; +/* +* Reader optimistic lock stealing +* +* We can take the read lock directly without doing +* rwsem_optimistic_spin() if the conditions are right. +* Also wake up other readers if it is the first reader. +*/ +if (!(count & (RWSEM_WRITER_LOCKED |RWSEM_FLAG_HANDOFF )) && +rwsem_no_spinners (sem)) { +rwsem_set_reader_owned (sem); +lockevent_inc (rwsem_rlock_steal); +if (rcnt ==1 ) + goto wake_readers; +return sem; + } +/* * Save the current read-owner of rwsem, if available, and the * reader nonspinnable bit.
@@ -1048,6 +1075,7 @@ rwsem_down_read_slowpath(struct rw_semaphore *sem, long count, int state)* Wake up other readers in the wait list if the front * waiter is a reader. */ +wake_readers:if ((atomic_long_read (&sem->count) &RWSEM_FLAG_WAITERS )) {raw_spin_lock_irq (&sem->wait_lock);if (!list_empty (&sem->wait_list))
Signature · 1 line
2.38.1
PATCH 7/7 locking/rwsem: Remove reader optimistic spinning
In reply to Shaoying XuFrom: Waiman Long <[email protected]>
commit 617f3ef95177840c77f59c2aec1029d27d5547d6 upstream
Reader optimistic spinning is helpful when the reader critical section is short and there aren't that many readers around. It also improves the chance that a reader can get the lock as writer optimistic spinning disproportionally favors writers much more than readers.
Since commit d3681e269fff ("locking/rwsem: Wake up almost all readers in wait queue"), all the waiting readers are woken up so that they can all get the read lock and run in parallel. When the number of contending readers is large, allowing reader optimistic spinning will likely cause reader fragmentation where multiple smaller groups of readers can get the read lock in a sequential manner separated by writers. That reduces reader parallelism.
One possible way to address that drawback is to limit the number of readers (preferably one) that can do optimistic spinning. These readers act as representatives of all the waiting readers in the wait queue as they will wake up all those waiting readers once they get the lock.
Alternatively, as reader optimistic lock stealing has already enhanced fairness to readers, it may be easier to just remove reader optimistic spinning and simplifying the optimistic spinning code as a result.
Performance measurements (locking throughput kops/s) using a locking microbenchmark with 50/50 reader/writer distribution and turbo-boost disabled was done on a 2-socket Cascade Lake system (48-core 96-thread) to see the impacts of these changes:
1) Vanilla - 5.10-rc3 kernel
2) Before - 5.10-rc3 kernel with previous patches in this series
2) limit-rspin - 5.10-rc3 kernel with limited reader spinning patch
3) no-rspin - 5.10-rc3 kernel with reader spinning disabled
# of threads CS Load Vanilla Before limit-rspin no-rspin
------------ ------- ------- ------ ----------- --------
2 1 5,185 5,662 5,214 5,077
4 1 5,107 4,983 5,188 4,760
8 1 4,782 4,564 4,720 4,628
16 1 4,680 4,053 4,567 3,402
32 1 4,299 1,115 1,118 1,098
64 1 3,218 983 1,001 957
96 1 1,938 944 957 930 2 20 2,008 2,128 2,264 1,665
4 20 1,390 1,033 1,046 1,101
8 20 1,472 1,155 1,098 1,213
16 20 1,332 1,077 1,089 1,122
32 20 967 914 917 980
64 20 787 874 891 858
96 20 730 836 847 844 2 100 372 356 360 355
4 100 492 425 434 392
8 100 533 537 529 538
16 100 548 572 568 598
32 100 499 520 527 537
64 100 466 517 526 512
96 100 406 497 506 509The column "CS Load" represents the number of pause instructions issued in the locking critical section. A CS load of 1 is extremely short and is not likey in real situations. A load of 20 (moderate) and 100 (long) are more realistic.
It can be seen that the previous patches in this series have reduced performance in general except in highly contended cases with moderate or long critical sections that performance improves a bit. This change is mostly caused by the "Prevent potential lock starvation" patch that reduce reader optimistic spinning and hence reduce reader fragmentation.
The patch that further limit reader optimistic spinning doesn't seem to have too much impact on overall performance as shown in the benchmark data.
The patch that disables reader optimistic spinning shows reduced performance at lightly loaded cases, but comparable or slightly better performance on with heavier contention.
This patch just removes reader optimistic spinning for now. As readers are not going to do optimistic spinning anymore, we don't need to consider if the OSQ is empty or not when doing lock stealing.
--- kernel/locking/lock_events_list.h | 5 +- kernel/locking/rwsem.c | 284 +++++------------------------- 2 files changed, 49 insertions(+), 240 deletions(-)
kernel/locking/lock_events_list.h +1 -4
@@ -56,12 +56,9 @@ LOCK_EVENT(rwsem_sleep_reader) /* # of reader sleeps */ LOCK_EVENT(rwsem_sleep_writer) /* # of writer sleeps */ LOCK_EVENT(rwsem_wake_reader) /* # of reader wakeups */ LOCK_EVENT(rwsem_wake_writer) /* # of writer wakeups */ -LOCK_EVENT(rwsem_opt_rlock) /* # of opt-acquired read locks */ -LOCK_EVENT(rwsem_opt_wlock) /* # of opt-acquired write locks */ +LOCK_EVENT(rwsem_opt_lock) /* # of opt-acquired write locks */ LOCK_EVENT(rwsem_opt_fail) /* # of failed optspins */ LOCK_EVENT(rwsem_opt_nospin) /* # of disabled optspins */ -LOCK_EVENT(rwsem_opt_norspin) /* # of disabled reader-only optspins */ -LOCK_EVENT(rwsem_opt_rlock2) /* # of opt-acquired 2ndary read locks */ LOCK_EVENT(rwsem_rlock) /* # of read locks acquired */ LOCK_EVENT(rwsem_rlock_steal) /* # of read locks by lock stealing */ LOCK_EVENT(rwsem_rlock_fast) /* # of fast read locks acquired */
kernel/locking/rwsem.c +48 -236
511 lines not on this page · raw message
Signature · 1 line
2.38.1
Greg KH
maintainerQuoted 19 lines · Shaoying Xu
This patch series is to remove reader optimistic spinning in kernel 5.10 to improve the MongoDB performance. Performance measurements (10 times running average of overall throughput ops/sec) are using MongoDB 5.0.11 and YCSB [1] microbenchmark with workloadA [2] on AWS EC2 m5.4xlarge/m6g.4xlarge (16-vCPU 64GiB-memory) instances with a 512GB EBS IO1 drive disk with 5000 IOPS and separating MongoDB and YCSB load generator on 2 instances and setting recordcount=25000000 and operationcount=10000000 to see the impacts of these changes:
Before - v5.10.165 kernel in OS Amazon Linux 2
After - v5.10.165 kernel with reader spinning disabled in OS Amazon Linux 2| Arch | Instance Type | Before | After | |---------+---------------+---------+---------| | x86_64 | m5.4xlarge | 37365.4 | 42373.9 | |---------+---------------+---------+---------| | aarch64 | m6g.4xlarge | 33823.1 | 43113.7 | |---------+---------------+---------+---------|
Quoted 4 lines
It can be seen that the MongoDB throughput can be improved around 13% in
x86_64and 27% in aarch64 after disabling reader optimistic spinning and these patches can be applied to 5.10 with no conflict so we wonder if it's possible to backport them to stable 5.10?
This is, frankly, crazy. :)
This is great that you did this work and found this out, but really, shouldn't you have done the less work and just moved to 5.15.y instead? You're going to have to do that anyway, what's preventing that from happening now, with the HUGE justification that you get a big workload increase and power savings (i.e. real money)?
So now you just delay the inevitable and spend more work overall (i.e. the backport work now, and the 5.15.y move later?) This feels like a bad management decision somewhere, who do I need to talk to to resolve this?
thanks,
greg k-h
Quoted 5 lines
This is great that you did this work and found this out, but really, shouldn't you have done the less work and just moved to 5.15.y instead? You're going to have to do that anyway, what's preventing that from happening now, with the HUGE justification that you get a big workload increase and power savings (i.e. real money)?
Hey Greg,
We are actually shipping kernel 5.15 as part of Amazon Linux kernel releases so theoretically moving to 5.15 should be the way to go however usually the relevant teams take some time for workload specific testing and benchmark before they do a major upgrade like moving from 5.10 to 5.15. We usually ask whoever is reporting a regression/bug/kernel enhancement to run with the latest kernel as you said while sometimes we backport fixes if the production migration to the latest kernel is something that will take time for the reasons I mentioned above. We thought that this performance improvement will also be beneficial for Linux 5.10 users hence we preferred these patches to be merged to the stable 5.10 rather than us just consume them as downstream patches. We are currently working with the relevant team on a plan for the possible 5.15 migration as a long term solution.
Thank you.
Hazem
On 09/02/2023, 10:37, "Greg KH" <[email protected] <mailto:[email protected]> <mailto:[email protected] <mailto:[email protected]>> <mailto:[email protected] <mailto:[email protected]> <mailto:[email protected] <mailto:[email protected]>>> <mailto:[email protected] <mailto:[email protected]> <mailto:[email protected] <mailto:[email protected]>> <mailto:[email protected] <mailto:[email protected]> <mailto:[email protected] <mailto:[email protected]>>>>> wrote:
CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
Quoted 19 lines · Shaoying Xu
This patch series is to remove reader optimistic spinning in kernel 5.10 to improve the MongoDB performance. Performance measurements (10 times running average of overall throughput ops/sec) are using MongoDB 5.0.11 and YCSB [1] microbenchmark with workloadA [2] on AWS EC2 m5.4xlarge/m6g.4xlarge (16-vCPU 64GiB-memory) instances with a 512GB EBS IO1 drive disk with 5000 IOPS and separating MongoDB and YCSB load generator on 2 instances and setting recordcount=25000000 and operationcount=10000000 to see the impacts of these changes:
Before - v5.10.165 kernel in OS Amazon Linux 2
After - v5.10.165 kernel with reader spinning disabled in OS Amazon Linux 2| Arch | Instance Type | Before | After | |---------+---------------+---------+---------| | x86_64 | m5.4xlarge | 37365.4 | 42373.9 | |---------+---------------+---------+---------| | aarch64 | m6g.4xlarge | 33823.1 | 43113.7 | |---------+---------------+---------+---------|
Quoted 4 lines
It can be seen that the MongoDB throughput can be improved around 13% in
x86_64and 27% in aarch64 after disabling reader optimistic spinning and these patches can be applied to 5.10 with no conflict so we wonder if it's possible to backport them to stable 5.10?
This is, frankly, crazy. :)
This is great that you did this work and found this out, but really, shouldn't you have done the less work and just moved to 5.15.y instead? You're going to have to do that anyway, what's preventing that from happening now, with the HUGE justification that you get a big workload increase and power savings (i.e. real money)?
So now you just delay the inevitable and spend more work overall (i.e. the backport work now, and the 5.15.y move later?) This feels like a bad management decision somewhere, who do I need to talk to to resolve this?
thanks,
greg k-h
Greg KH
maintainerQuoted 13 lines · Hazem
Quoted 5 lines
This is great that you did this work and found this out, but really, shouldn't you have done the less work and just moved to 5.15.y instead? You're going to have to do that anyway, what's preventing that from happening now, with the HUGE justification that you get a big workload increase and power savings (i.e. real money)?
Quoted 9 lines
Hey Greg,
Hi,
Odd whitespace, you should fix your email client :)
Quoted 1 line
We are actually shipping kernel 5.15 as part of Amazon Linux kernel releases so theoretically moving to 5.15 should be the way to go however usually the relevant teams take some time for workload specific testing and benchmark before they do a major upgrade like moving from 5.10 to 5.15. We usually ask whoever is reporting a regression/bug/kernel enhancement to run with the latest kernel as you said while sometimes we backport fixes if the production migration to the latest kernel is something that will take time for the reasons I mentioned above. We thought that this performance improvement will also be beneficial for Linux 5.10 users hence we preferred these patches to be merged to the stable 5.10 rather than us just consume them as downstream patches. We are currently working with the relevant team on a plan for the possible 5.15 migration as a long term solution.
And use some \n characters :)
But this isn't a regression, it's a speedup. And a good reason to use a newer kernel version. What type of guarantees that these changes work properly and have all needed future bugfixes applied to them? How were they tested?
I am loath to want to replace something as core as this without a lot of testing and verification and agreement from the subsystem authors/maintainers that this is ok to make.
Seriously, just move to 5.15.y or 6.1.y, that will be easier for you in the long run, the amount of testing and validation should have been the same for this small patchset as it would be for a kernel update, so there shouldn't be any issues here.
thanks,
greg k-h