MINOR: time: avoid overwriting the same values of global_now
In tv_update_date(), we calculate the new global date based on the local one. It's very likely that other threads will end up with the exact same now_ms date (at 1 million wakeups/s it happens 99.9% of the time), and even the microsecond was measured to remain unchanged ~70% of the time with 16 threads, simply because sometimes another thread already updated a more recent version of it. In such cases, performing a CAS to the global variable requires a cache line flush which brings nothing. By checking if they're changed before writing, we can divide by about 6 the number of writes to the global variables, hence the overall contention. In addition, it's worth noting that all threads will want to update at the same time, so let's place a cpu relax call before trying again, this will spread attempts apart.
This commit is contained in:
parent
481795de13
commit
4d01f3dcdc
|
@ -252,8 +252,9 @@ void tv_update_date(int max_wait, int interrupted)
|
|||
/* let's try to update the global <now> (both in timeval
|
||||
* and ms forms) or loop again.
|
||||
*/
|
||||
} while (!_HA_ATOMIC_CAS(&global_now, &old_now, new_now) ||
|
||||
!_HA_ATOMIC_CAS(&global_now_ms, &old_now_ms, now_ms));
|
||||
} while (((new_now != old_now && !_HA_ATOMIC_CAS(&global_now, &old_now, new_now)) ||
|
||||
(now_ms != old_now_ms && !_HA_ATOMIC_CAS(&global_now_ms, &old_now_ms, now_ms))) &&
|
||||
__ha_cpu_relax());
|
||||
|
||||
/* <now> and <now_ms> are now updated to the last value of global_now
|
||||
* and global_now_ms, which were also monotonically updated. We can
|
||||
|
|
Loading…
Reference in New Issue