Skip to content

Commit 781764e

Browse files
committed
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 <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 1535cb8 commit 781764e

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

kernel/time/posix-timers.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
*/
1212
#include <linux/compat.h>
1313
#include <linux/compiler.h>
14-
#include <linux/hash.h>
1514
#include <linux/init.h>
15+
#include <linux/jhash.h>
1616
#include <linux/interrupt.h>
1717
#include <linux/list.h>
1818
#include <linux/memblock.h>
@@ -47,11 +47,11 @@ struct timer_hash_bucket {
4747

4848
static struct {
4949
struct timer_hash_bucket *buckets;
50-
unsigned long bits;
50+
unsigned long mask;
5151
} __timer_data __ro_after_init __aligned(2*sizeof(long));
5252

5353
#define timer_buckets (__timer_data.buckets)
54-
#define timer_hashbits (__timer_data.bits)
54+
#define timer_hashmask (__timer_data.mask)
5555

5656
static const struct k_clock * const posix_clocks[];
5757
static const struct k_clock *clockid_to_kclock(const clockid_t id);
@@ -87,7 +87,7 @@ DEFINE_CLASS_IS_COND_GUARD(lock_timer);
8787

8888
static struct timer_hash_bucket *hash_bucket(struct signal_struct *sig, unsigned int nr)
8989
{
90-
return &timer_buckets[hash_32(hash32_ptr(sig) ^ nr, timer_hashbits)];
90+
return &timer_buckets[jhash2((u32 *)&sig, sizeof(sig) / sizeof(u32), nr) & timer_hashmask];
9191
}
9292

9393
static struct k_itimer *posix_timer_by_id(timer_t id)
@@ -1513,7 +1513,7 @@ static int __init posixtimer_init(void)
15131513
timer_buckets = alloc_large_system_hash("posixtimers", sizeof(*timer_buckets),
15141514
size, 0, 0, &shift, NULL, size, size);
15151515
size = 1UL << shift;
1516-
timer_hashbits = ilog2(size);
1516+
timer_hashmask = size - 1;
15171517

15181518
for (i = 0; i < size; i++) {
15191519
spin_lock_init(&timer_buckets[i].lock);

0 commit comments

Comments
 (0)