summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2025-03-08 17:48:40 +0100
committerThomas Gleixner <tglx@linutronix.de>2025-03-13 12:07:17 +0100
commit781764e0b4394fbd8e8eb39195f8a076b60808b3 (patch)
tree6d6d67491ea19bfbff9d81c8b2134e7d9680282d
parent1535cb80286e6fbc834f075039f85274538543c7 (diff)
posix-timers: Switch to jhash32()
The hash distribution of hash_32() is suboptimal. jhash32() provides a way better distribution, which evens out the length of the hash bucket lists, which in turn avoids large outliers in list walk times. Due to the sparse ID space (thanks CRIU) there is no guarantee that the timers will be fully evenly distributed over the hash buckets, but the behaviour is way better than with hash_32() even for randomly sparse ID spaces. For a pathological test case with 64 processes creating and accessing 20000 timers each, this results in a runtime reduction of ~10% and a significantly reduced runtime variation. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20250308155624.279080328@linutronix.de
-rw-r--r--kernel/time/posix-timers.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 23f6d8bf0d89..0c4cee38d965 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -11,8 +11,8 @@
*/
#include <linux/compat.h>
#include <linux/compiler.h>
-#include <linux/hash.h>
#include <linux/init.h>
+#include <linux/jhash.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/memblock.h>
@@ -47,11 +47,11 @@ struct timer_hash_bucket {
static struct {
struct timer_hash_bucket *buckets;
- unsigned long bits;
+ unsigned long mask;
} __timer_data __ro_after_init __aligned(2*sizeof(long));
#define timer_buckets (__timer_data.buckets)
-#define timer_hashbits (__timer_data.bits)
+#define timer_hashmask (__timer_data.mask)
static const struct k_clock * const posix_clocks[];
static const struct k_clock *clockid_to_kclock(const clockid_t id);
@@ -87,7 +87,7 @@ DEFINE_CLASS_IS_COND_GUARD(lock_timer);
static struct timer_hash_bucket *hash_bucket(struct signal_struct *sig, unsigned int nr)
{
- return &timer_buckets[hash_32(hash32_ptr(sig) ^ nr, timer_hashbits)];
+ return &timer_buckets[jhash2((u32 *)&sig, sizeof(sig) / sizeof(u32), nr) & timer_hashmask];
}
static struct k_itimer *posix_timer_by_id(timer_t id)
@@ -1513,7 +1513,7 @@ static int __init posixtimer_init(void)
timer_buckets = alloc_large_system_hash("posixtimers", sizeof(*timer_buckets),
size, 0, 0, &shift, NULL, size, size);
size = 1UL << shift;
- timer_hashbits = ilog2(size);
+ timer_hashmask = size - 1;
for (i = 0; i < size; i++) {
spin_lock_init(&timer_buckets[i].lock);