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;
}
next prev parent 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).