netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "'tgraf@suug.ch'" <tgraf@suug.ch>
To: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David Laight <David.Laight@ACULAB.COM>,
	David Miller <davem@davemloft.net>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	Eric Dumazet <eric.dumazet@gmail.com>
Subject: Re: [v1 PATCH 1/14] rhashtable: Remove shift from bucket_table
Date: Wed, 18 Mar 2015 09:51:02 +0000	[thread overview]
Message-ID: <20150318095102.GL17829@casper.infradead.org> (raw)
In-Reply-To: <20150317215638.GA16776@gondor.apana.org.au>

On 03/18/15 at 08:56am, Herbert Xu wrote:
> Actually 75% is just as bad.  To test that just repeat my script
> above and add head -n $((65536 / 4 * 3)) before the first sort.
> 
> My point is that to get below anything like a chain length limit
> of 2 (or even 4), your hash table is going to be mostly empty.
> OK 0.1% might be an exaggeration but it's certainly nowhere near 50%
> as your hash table size grows.
> 
> Please actually try out my test, here is a C program that will help
> you do it:

Thanks for providing that C program. I played around with it and
noticed a small typo which I fixed up. I'm attaching the version
I've used at the end of the mail.

Maybe there is a thinko on my part but the results I'm getting are
very impressive. I have a very hard time to produce more than a
single hash conflict for sequences up to 0..2^27.

I also tried with a pseudo random value for the u32 part of the key
instead of the sequence  number and got the same results.

I'm running it like this:
for i in $(seq 1 27); do \
echo $i: && ./jhash $((2**$i)) | uniq -D | uniq -c \
done

1:
2:
3:
      3 0x1
4:
      2 0xc
5:
6:
      2 0x2b
7:
8:
9:
10:
11:
      2 0x1c9
12:
13:
      2 0x9c7
      2 0x4e9
14:
15:
      2 0x5c8
16:
17:
18:
      2 0x34cb2
      2 0x21fd0
19:
      2 0x61fd0
      2 0x6e82f
20:
      2 0x61fd0
      2 0x6e82f
      2 0xfd571
21:
      2 0x1a0e02
      2 0x1776ea
22:
      2 0x379099
23:
      2 0x2650b6
      2 0x6dc5b5
      2 0x648fe1
      2 0x543446
24:
      2 0x8d60e0
      2 0x8726e5
25:
      2 0x1225f30
26:
      2 0x3a136f4
27:


--- jhash.c ---

#include <stdio.h>

typedef unsigned char u8;
typedef unsigned int u32;

static inline u32 rol32(u32 word, unsigned int shift)
{
	return (word << shift) | (word >> (32 - shift));
}

/* Best hash sizes are of power of two */
#define jhash_size(n)   ((u32)1<<(n))
/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
#define jhash_mask(n)   (jhash_size(n)-1)

/* __jhash_mix -- mix 3 32-bit values reversibly. */
#define __jhash_mix(a, b, c)			\
{						\
	a -= c;  a ^= rol32(c, 4);  c += b;	\
	b -= a;  b ^= rol32(a, 6);  a += c;	\
	c -= b;  c ^= rol32(b, 8);  b += a;	\
	a -= c;  a ^= rol32(c, 16); c += b;	\
	b -= a;  b ^= rol32(a, 19); a += c;	\
	c -= b;  c ^= rol32(b, 4);  b += a;	\
}

/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
#define __jhash_final(a, b, c)			\
{						\
	c ^= b; c -= rol32(b, 14);		\
	a ^= c; a -= rol32(c, 11);		\
	b ^= a; b -= rol32(a, 25);		\
	c ^= b; c -= rol32(b, 16);		\
	a ^= c; a -= rol32(c, 4);		\
	b ^= a; b -= rol32(a, 14);		\
	c ^= b; c -= rol32(b, 24);		\
}

#define __get_unaligned_cpu32(x) (*(u32 *)(x))

/* An arbitrary initial parameter */
#define JHASH_INITVAL		0xdeadbeef

/* jhash - hash an arbitrary key
 * @k: sequence of bytes as key
 * @length: the length of the key
 * @initval: the previous hash, or an arbitray value
 *
 * The generic version, hashes an arbitrary sequence of bytes.
 * No alignment or length assumptions are made about the input key.
 *
 * Returns the hash value of the key. The result depends on endianness.
 */
static inline u32 jhash(const void *key, u32 length, u32 initval)
{
	u32 a, b, c;
	const u8 *k = key;

	/* Set up the internal state */
	a = b = c = JHASH_INITVAL + length + initval;

	/* All but the last block: affect some 32 bits of (a,b,c) */
	while (length > 12) {
		a += __get_unaligned_cpu32(k);
		b += __get_unaligned_cpu32(k + 4);
		c += __get_unaligned_cpu32(k + 8);
		__jhash_mix(a, b, c);
		length -= 12;
		k += 12;
	}
	/* Last block: affect all 32 bits of (c) */
	/* All the case statements fall through */
	switch (length) {
	case 12: c += (u32)k[11]<<24;
	case 11: c += (u32)k[10]<<16;
	case 10: c += (u32)k[9]<<8;
	case 9:  c += k[8];
	case 8:  b += (u32)k[7]<<24;
	case 7:  b += (u32)k[6]<<16;
	case 6:  b += (u32)k[5]<<8;
	case 5:  b += k[4];
	case 4:  a += (u32)k[3]<<24;
	case 3:  a += (u32)k[2]<<16;
	case 2:  a += (u32)k[1]<<8;
	case 1:  a += k[0];
		 __jhash_final(a, b, c);
	case 0: /* Nothing left to add */
		break;
	}

	return c;
}

/* jhash2 - hash an array of u32's
 * @k: the key which must be an array of u32's
 * @length: the number of u32's in the key
 * @initval: the previous hash, or an arbitray value
 *
 * Returns the hash value of the key.
 */
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
{
	u32 a, b, c;

	/* Set up the internal state */
	a = b = c = JHASH_INITVAL + (length<<2) + initval;

	/* Handle most of the key */
	while (length > 3) {
		a += k[0];
		b += k[1];
		c += k[2];
		__jhash_mix(a, b, c);
		length -= 3;
		k += 3;
	}

	/* Handle the last 3 u32's: all the case statements fall through */
	switch (length) {
	case 3: c += k[2];
	case 2: b += k[1];
	case 1: a += k[0];
		__jhash_final(a, b, c);
	case 0:	/* Nothing left to add */
		break;
	}

	return c;
}


/* jhash_3words - hash exactly 3, 2 or 1 word(s) */
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
{
	a += JHASH_INITVAL;
	b += JHASH_INITVAL;
	c += initval;

	__jhash_final(a, b, c);

	return c;
}

static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
{
	return jhash_3words(a, b, 0, initval);
}

static inline u32 jhash_1word(u32 a, u32 initval)
{
	return jhash_3words(a, 0, 0, initval);
}

int main(int argc, char **argv)
{
	int i;
	struct {
		void *s;
		void *t;
		u32 l;
	} k = { .s = 0 };
	int total;
	u32 initval;

	total = atoi(argv[1]);
	srandom(time(0));
	initval = random();

	for (i = 0; i < total; i++) {
		k.l = i;
		printf("0x%x\n", jhash2((u32 *)&k, sizeof(k)/4, initval) & (total - 1));
	}

	return 0;
}

  reply	other threads:[~2015-03-18  9:51 UTC|newest]

Thread overview: 113+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-13  9:56 [PATCH 0/6] rhashtable: Fixes + cleanups + preparation for multiple rehash Herbert Xu
2015-03-13  9:57 ` [PATCH 1/6] rhashtable: Fix walker behaviour during rehash Herbert Xu
2015-03-13 15:50   ` Thomas Graf
2015-03-13 23:42     ` Herbert Xu
2015-03-14  0:06       ` Thomas Graf
2015-03-13  9:57 ` [PATCH 2/6] rhashtable: Use SINGLE_DEPTH_NESTING Herbert Xu
2015-03-13 15:40   ` Thomas Graf
2015-03-13  9:57 ` [PATCH 3/6] rhashtable: Move seed init into bucket_table_alloc Herbert Xu
2015-03-13 10:03   ` Daniel Borkmann
2015-03-13 11:33   ` David Laight
2015-03-13 11:40     ` Herbert Xu
2015-03-13 15:40   ` Thomas Graf
2015-03-13  9:57 ` [PATCH 4/6] rhashtable: Free bucket tables asynchronously after rehash Herbert Xu
2015-03-13 15:42   ` Thomas Graf
2015-03-13  9:57 ` [PATCH 5/6] rhashtable: Add rehash counter to bucket_table Herbert Xu
2015-03-13 13:51   ` Thomas Graf
2015-03-14  2:49     ` Herbert Xu
2015-03-13  9:57 ` [PATCH 6/6] rhashtable: Move future_tbl into struct bucket_table Herbert Xu
2015-03-13 16:13   ` Thomas Graf
2015-03-13 13:57 ` [PATCH 0/6] rhashtable: Fixes + cleanups + preparation for multiple rehash Thomas Graf
2015-03-13 16:25 ` David Miller
2015-03-14  2:51   ` Herbert Xu
2015-03-14  2:53 ` [v2 PATCH " Herbert Xu
2015-03-14  2:57   ` [v2 PATCH 1/6] rhashtable: Fix walker behaviour during rehash Herbert Xu
2015-03-14  2:57   ` [v2 PATCH 2/6] rhashtable: Use SINGLE_DEPTH_NESTING Herbert Xu
2015-03-14  2:57   ` [v2 PATCH 3/6] rhashtable: Move seed init into bucket_table_alloc Herbert Xu
2015-03-14  2:57   ` [v2 PATCH 4/6] rhashtable: Free bucket tables asynchronously after rehash Herbert Xu
2015-03-14  2:57   ` [v2 PATCH 5/6] rhashtable: Add rehash counter to bucket_table Herbert Xu
2015-03-14  2:57   ` [v2 PATCH 6/6] rhashtable: Move future_tbl into struct bucket_table Herbert Xu
2015-03-15  5:36   ` [v2 PATCH 0/6] rhashtable: Fixes + cleanups + preparation for multiple rehash David Miller
2015-03-15 10:10     ` [v1 PATCH 0/6] rhashtable: Fix two bugs caused by multiple rehash preparation Herbert Xu
2015-03-15 10:12       ` [v1 PATCH 1/2] rhashtable: Fix use-after-free in rhashtable_walk_stop Herbert Xu
2015-03-15 10:12       ` [v1 PATCH 2/2] rhashtable: Fix rhashtable_remove failures Herbert Xu
2015-03-15 10:43       ` [v1 PATCH 0/14] rhashtable: Kill shift/Key netlink namespace/Merge jhash Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 1/14] rhashtable: Remove shift from bucket_table Herbert Xu
2015-03-17 10:51           ` David Laight
2015-03-17 10:56             ` tgraf
2015-03-17 11:00               ` Herbert Xu
2015-03-17 11:22                 ` tgraf
2015-03-17 11:27                   ` Herbert Xu
2015-03-17 11:57                     ` tgraf
2015-03-17 12:13                       ` David Laight
2015-03-17 12:18                         ` 'tgraf@suug.ch'
2015-03-17 12:20                         ` Herbert Xu
2015-03-17 12:40                           ` 'tgraf@suug.ch'
2015-03-17 13:06                             ` David Laight
2015-03-17 21:56                             ` Herbert Xu
2015-03-18  9:51                               ` 'tgraf@suug.ch' [this message]
2015-03-18  9:55                                 ` Herbert Xu
2015-03-18 10:08                                   ` 'tgraf@suug.ch'
2015-03-18 10:12                                     ` Herbert Xu
2015-03-18 10:26                                       ` David Laight
2015-03-18 10:44                                       ` 'tgraf@suug.ch'
2015-03-17 11:22                 ` David Laight
2015-03-17 11:25                   ` Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 2/14] rhashtable: Introduce max_size/min_size Herbert Xu
2015-03-15 15:12           ` Sergei Shtylyov
2015-03-15 20:21             ` Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 3/14] netlink: Use rhashtable max_size instead of max_shift Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 4/14] tipc: " Herbert Xu
2015-03-15 15:13           ` Sergei Shtylyov
2015-03-15 10:44         ` [v1 PATCH 5/14] test_rhashtable: " Herbert Xu
2015-03-16  3:50           ` David Miller
2015-03-15 10:44         ` [v1 PATCH 6/14] rhashtable: Remove max_shift and min_shift Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 7/14] netfilter: Use rhashtable_lookup instead of lookup_compare Herbert Xu
2015-03-16  8:28           ` Thomas Graf
2015-03-16  9:14             ` Herbert Xu
2015-03-16  9:28               ` Thomas Graf
2015-03-16 11:13               ` Patrick McHardy
2015-03-20  8:55                 ` Herbert Xu
2015-03-20  9:22                   ` Patrick McHardy
2015-03-20  9:27                     ` Herbert Xu
2015-03-20  9:59                       ` Patrick McHardy
2015-03-20 10:16                         ` Herbert Xu
2015-03-20 10:27                           ` Patrick McHardy
2015-03-20 21:47                             ` Herbert Xu
2015-03-20 21:56                               ` Thomas Graf
2015-03-20 21:57                                 ` Herbert Xu
2015-03-20 22:07                                   ` Thomas Graf
2015-03-20 22:10                                     ` Herbert Xu
2015-03-20 22:23                                       ` Thomas Graf
2015-03-20 22:25                                         ` Herbert Xu
2015-03-20 22:36                                           ` Thomas Graf
2015-03-21  5:25                                             ` Patrick McHardy
2015-03-21  5:23                               ` Patrick McHardy
2015-03-20  9:36               ` Herbert Xu
2015-03-20 10:02                 ` Patrick McHardy
2015-03-15 10:44         ` [v1 PATCH 8/14] rhashtable: Fix support of objects with no accessible keys Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 9/14] netlink: Move namespace into hash key Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 10/14] rhashtable: Rip out obsolete compare interface Herbert Xu
2015-03-16  9:35           ` Thomas Graf
2015-03-15 10:44         ` [v1 PATCH 11/14] rhashtable: Allow hashfn to be unset Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 12/14] netlink: Use default rhashtable hashfn Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 13/14] tipc: " Herbert Xu
2015-03-15 10:44         ` [v1 PATCH 14/14] netfilter: " Herbert Xu
2015-03-16  4:01         ` [v1 PATCH 0/14] rhashtable: Kill shift/Key netlink namespace/Merge jhash David Miller
2015-03-16  4:18           ` Herbert Xu
2015-03-16  4:30             ` David Miller
2015-03-16  4:33               ` Herbert Xu
2015-03-16  4:40                 ` David Miller
2015-03-16 11:26                   ` Herbert Xu
2015-03-16 20:25                     ` David Miller
2015-03-18  9:01         ` [v2 PATCH 1/6] rhashtable: Remove shift from bucket_table Herbert Xu
2015-03-18  9:01         ` [v2 PATCH 2/6] rhashtable: Introduce max_size/min_size Herbert Xu
2015-03-18 10:55           ` Thomas Graf
2015-03-18 16:47             ` David Miller
2015-03-18 16:51             ` David Laight
2015-03-18  9:01         ` [v2 PATCH 3/6] netlink: Use rhashtable max_size instead of max_shift Herbert Xu
2015-03-18  9:01         ` [v2 PATCH 4/6] tipc: Use rhashtable max/min_size instead of max/min_shift Herbert Xu
2015-03-18  9:01         ` [v2 PATCH 5/6] test_rhashtable: Use rhashtable max_size instead of max_shift Herbert Xu
2015-03-18  9:01         ` [v2 PATCH 6/6] rhashtable: Remove max_shift and min_shift Herbert Xu
2015-03-15 10:43       ` [v1 PATCH 0/6] rhashtable: Fix two bugs caused by multiple rehash preparation Herbert Xu
2015-03-16  2:23       ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150318095102.GL17829@casper.infradead.org \
    --to=tgraf@suug.ch \
    --cc=David.Laight@ACULAB.COM \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).