Re: [rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2011-01-20 Thread Alexander Leidinger
Quoting Gleb Kurtsou  (from Fri, 24 Dec 2010  
00:46:20 +0200):



Hi,

I've recently noticed that hash table use in nullfs was inefficient, 1/3
to half of buckets remained unused. I've started investigating it
further and came across SuperFastHash hashing function, SFH
(SuperFastHash) has BSD license, used in WebKit and other open source
projects. Detailed description and Comparision with FNV and Bob Jenkin's
hash can be found here:
http://www.azillionmonkeys.com/qed/hash.html


I found some web pages which tell about an unfair speed comparision  
and about a collision problem in SFH:
  
http://coding.derkeiler.com/Archive/General/comp.programming/2005-03/0650.html

 http://www.team5150.com/~andrew/blog/2007/03/breaking_superfasthash.html
 http://blog.clawpaws.net/post/2007/04/22/Good-Hash-Functions

It may be that this is not an issue for the use case we have here, but  
blindly replacing it without looking at the above web pages looks a  
little bit risky to me.


Bye,
Alexander.

--
The use of money is all the advantage there is to having money.
-- Benjamin Franklin

http://www.Leidinger.netAlexander @ Leidinger.net: PGP ID = B0063FE7
http://www.FreeBSD.org   netchild @ FreeBSD.org  : PGP ID = 72077137
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: [rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2010-12-26 Thread Gleb Kurtsou
On (26/12/2010 15:20), Ivan Voras wrote:
> On 26 December 2010 14:24, Gleb Kurtsou  wrote:
> > On (25/12/2010 20:29), Ivan Voras wrote:
> >> On 23.12.2010 23:46, Gleb Kurtsou wrote:
> >>
> >> > For testing I've used dbench with 16 processes on 1 Gb swap back md
> >> > device, UFS + SoftUpdates:
> >> > Old hash (Mb/s): 599.94  600.096 599.536
> >> > SFH hash (Mb/s): 612.439 612.341 609.673
> >> >
> >> > It's just ~1% improvement, but dbench is not a VFS metadata intensive
> >> > benchmark. Subjectively it feels faster accessing maildir mailboxes
> >> > with ~10.000 messages : )
> >>
> >> Try blogbench if you need metadata-intensive operations, or even fsx.
> 
> > blogbench should be good, but I've always had hard time interpreting its
> > results. Besides results tend to very a lot, there is no way to set seed
> > value like in fsx, so that I could run exactly the same test in different
> > configurations.
> 
> I think the exact sequence of blogbench operations depends on duration
> of previous operations (it's multithreaded) so from that angle you are
Why should it? Operation order in dbench or fsx doesn't depend on
duration of previous operations.

> right - you can't do a repeatable run except in the trivial cases. On
> the other hand, it uses rand() without seeding it with
> srand()/sranddev() so this part is actually very repeatable :)
I've once tried to make its behaviour more predictable, I can't find
the patch and can't recall any specifics, but there were architectural
issues. You are right, setting seed and calling rand() should give
stable results, that's what I was trying to achieve.

The other way to work around such "limitation" is too run sufficiently
large number of tests. Which requires patience :)

> > fsx is a different beast, it reads/writes/truncates at random offsets -
> > great tool for debugging mmap/truncate issues. Patch doesn't improve it
> > in any way.
> 
> It depends on what metadata operations you require - blogbench will
> create, find and write files (if we ignore atime); fsx will create a
> decent amount of traffic with file size and mtime changes. In your
> case you'll probably need to run it on a memory file system or tmpfs
> due to sensitivity to disk IO latencies (if your improvements is on
> the order of few percent).
I meant create/readdir/remove as metadata intensive operations -- blogbench
is very good for it. fsx creates single file.

Most people will only notice changes in vfs_cache.c and UFS' dirhash,
that's 600 Mb/s vs 613 Mb/s improvement I've written about above.

I'd appreciate if someone could benchmark if_lagg, it was using hash32
for binary data, which could result in poor hash table usage, which
could possibly make most of the data go on single interface. But there
would be hardly any performance improvement due to limited network
bandwidth. Besides old hash32 is faster than new SFH.

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: [rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2010-12-26 Thread Ivan Voras
On 26 December 2010 14:24, Gleb Kurtsou  wrote:
> On (25/12/2010 20:29), Ivan Voras wrote:
>> On 23.12.2010 23:46, Gleb Kurtsou wrote:
>>
>> > For testing I've used dbench with 16 processes on 1 Gb swap back md
>> > device, UFS + SoftUpdates:
>> > Old hash (Mb/s): 599.94  600.096 599.536
>> > SFH hash (Mb/s): 612.439 612.341 609.673
>> >
>> > It's just ~1% improvement, but dbench is not a VFS metadata intensive
>> > benchmark. Subjectively it feels faster accessing maildir mailboxes
>> > with ~10.000 messages : )
>>
>> Try blogbench if you need metadata-intensive operations, or even fsx.

> blogbench should be good, but I've always had hard time interpreting its
> results. Besides results tend to very a lot, there is no way to set seed
> value like in fsx, so that I could run exactly the same test in different
> configurations.

I think the exact sequence of blogbench operations depends on duration
of previous operations (it's multithreaded) so from that angle you are
right - you can't do a repeatable run except in the trivial cases. On
the other hand, it uses rand() without seeding it with
srand()/sranddev() so this part is actually very repeatable :)

> fsx is a different beast, it reads/writes/truncates at random offsets -
> great tool for debugging mmap/truncate issues. Patch doesn't improve it
> in any way.

It depends on what metadata operations you require - blogbench will
create, find and write files (if we ignore atime); fsx will create a
decent amount of traffic with file size and mtime changes. In your
case you'll probably need to run it on a memory file system or tmpfs
due to sensitivity to disk IO latencies (if your improvements is on
the order of few percent).
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: [rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2010-12-26 Thread Gleb Kurtsou
On (25/12/2010 20:29), Ivan Voras wrote:
> On 23.12.2010 23:46, Gleb Kurtsou wrote:
> 
> > For testing I've used dbench with 16 processes on 1 Gb swap back md
> > device, UFS + SoftUpdates:
> > Old hash (Mb/s): 599.94  600.096 599.536
> > SFH hash (Mb/s): 612.439 612.341 609.673
> > 
> > It's just ~1% improvement, but dbench is not a VFS metadata intensive
> > benchmark. Subjectively it feels faster accessing maildir mailboxes
> > with ~10.000 messages : )
> 
> Try blogbench if you need metadata-intensive operations, or even fsx.
blogbench should be good, but I've always had hard time interpreting its
results. Besides results tend to very a lot, there is no way to set seed
value like in fsx, so that I could run exactly the same test in different
configurations. I prefer to use blogbench for stability testing.

fsx is a different beast, it reads/writes/truncates at random offsets -
great tool for debugging mmap/truncate issues. Patch doesn't improve it
in any way.

> 
> ___
> freebsd-hackers@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: [rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2010-12-25 Thread Ivan Voras
On 23.12.2010 23:46, Gleb Kurtsou wrote:

> For testing I've used dbench with 16 processes on 1 Gb swap back md
> device, UFS + SoftUpdates:
> Old hash (Mb/s): 599.94  600.096 599.536
> SFH hash (Mb/s): 612.439 612.341 609.673
> 
> It's just ~1% improvement, but dbench is not a VFS metadata intensive
> benchmark. Subjectively it feels faster accessing maildir mailboxes
> with ~10.000 messages : )

Try blogbench if you need metadata-intensive operations, or even fsx.


___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: [rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2010-12-24 Thread Gleb Kurtsou
On (24/12/2010 00:46), Gleb Kurtsou wrote:
> Hi,
> 
> I've recently noticed that hash table use in nullfs was inefficient, 1/3
> to half of buckets remained unused. I've started investigating it
Nullfs patch I've forgotten to attach before.

It adds vfs.nullfs.buckets tunable to change number of hash table
buckets, vfs.nullfs.nodes sysctl to get number of active vnodes, and
increases default number of buckets from 16 to 32. Note that nullfs
nodes - are currently opened vnodes, so number is so low, one may want
to further increase it only if nullfs is heavily used (lots of null
mounts and active clients).

The patch requires SFH, but might be useful without it if
null_hash_mixptr() changed accordingly.

> further and came across SuperFastHash hashing function, SFH
> (SuperFastHash) has BSD license, used in WebKit and other open source
> projects. Detailed description and Comparision with FNV and Bob Jenkin's
> hash can be found here:
> http://www.azillionmonkeys.com/qed/hash.html
> 
> In my tests SFH (SuperFastHash) was 1.3 to 4 times faster than FNV (it
> depends on size of data being hashed) e.g. performance of hashing 56
> bytes struct (Core i5 CPU, 2 cores + 2 hyperthreads):
>   SFH -- 1339.79 MB/s
>   FNV -- 330.27 MB/s
> 
> I've prepared a patch to change FNV and hash32 with SFH in the tree.
> 
> For testing I've used dbench with 16 processes on 1 Gb swap back md
> device, UFS + SoftUpdates:
> Old hash (Mb/s): 599.94  600.096 599.536
> SFH hash (Mb/s): 612.439 612.341 609.673
> 
> It's just ~1% improvement, but dbench is not a VFS metadata intensive
> benchmark. Subjectively it feels faster accessing maildir mailboxes
> with ~10.000 messages : )
> 
> I'd also wish hash32 (often called Bernstein hash) to be replaced with
> better function (it might be FNV if not SFH). Hash32 is inappropriate
> for binary data that results in poor distribution.
> 
> Thanks,
> Gleb.
commit dd778e797cbfd821fc43ff74a8d5681ed2b93da1
Author: Gleb Kurtsou 
Date:   Thu Dec 16 08:13:58 2010 +0200

nullfs: Use SFH. Add sysctls to control hash table size

Add vfs.nullfs sysctls and tunable to change number hash table buckets
Increase default number of buckets to 32 (was 16)

diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 5717a01..2acd85b 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -36,18 +36,21 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
 
-#define LOG2_SIZEVNODE 8   /* log2(sizeof struct vnode) */
-#defineNNULLNODECACHE 16
+#defineNULL_BUCKETS_MIN16
+#defineNULL_BUCKETS_DEFAULT32
+#defineNULL_BUCKETS_TUNABLE"vfs.nullfs.buckets"
 
 /*
  * Null layer cache:
@@ -58,7 +61,7 @@
  */
 
 #defineNULL_NHASH(vp) \
-   (&null_node_hashtbl[(((uintptr_t)vp)>>LOG2_SIZEVNODE) & null_node_hash])
+   (&null_node_hashtbl[null_hash_mixptr(vp) & null_node_hash])
 
 static LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
 static u_long null_node_hash;
@@ -70,6 +73,15 @@ MALLOC_DEFINE(M_NULLFSNODE, "nullfs_node", "NULLFS vnode 
private part");
 static struct vnode * null_hashget(struct mount *, struct vnode *);
 static struct vnode * null_hashins(struct mount *, struct null_node *);
 
+static u_long null_nodes;
+static u_long null_buckets = NULL_BUCKETS_DEFAULT;
+
+SYSCTL_NODE(_vfs, OID_AUTO, nullfs, CTLFLAG_RW, 0, "null file system");
+SYSCTL_ULONG(_vfs_nullfs, OID_AUTO, nodes, CTLFLAG_RD, &null_nodes, 0,
+"Allocated nodes");
+SYSCTL_ULONG(_vfs_nullfs, OID_AUTO, buckets, CTLFLAG_RD, &null_buckets, 0,
+"Allocated node hash table buckets");
+
 /*
  * Initialise cache headers
  */
@@ -77,10 +89,15 @@ int
 nullfs_init(vfsp)
struct vfsconf *vfsp;
 {
-
NULLFSDEBUG("nullfs_init\n");   /* printed during system boot */
-   null_node_hashtbl = hashinit(NNULLNODECACHE, M_NULLFSHASH, 
&null_node_hash);
+   TUNABLE_ULONG_FETCH(NULL_BUCKETS_TUNABLE, &null_buckets);
+   if (null_buckets < NULL_BUCKETS_MIN)
+   null_buckets = NULL_BUCKETS_MIN;
+   else if (null_buckets > desiredvnodes)
+   null_buckets = NULL_BUCKETS_DEFAULT;
+   null_node_hashtbl = hashinit(null_buckets, M_NULLFSHASH, 
&null_node_hash);
mtx_init(&null_hashmtx, "nullhs", NULL, MTX_DEF);
+   null_nodes = 0;
return (0);
 }
 
@@ -94,6 +111,12 @@ nullfs_uninit(vfsp)
return (0);
 }
 
+static __inline uint32_t
+null_hash_mixptr(void *ptr)
+{
+   return (hash_sfh_buf(&ptr, sizeof(ptr), 33554467UL));
+}
+
 /*
  * Return a VREF'ed alias for lower vnode if already exists, else 0.
  * Lower vnode should be locked on entry and will be left locked on exit.
@@ -164,6 +187,7 @@ null_hashins(mp, xp)
}
}
LIST_INSERT_HEAD(hd, xp, null_hash);
+   null_nodes++;
mtx_unlock(&null_hashmtx);

[rfc] Replacing FNV and hash32 with Paul Hsieh's SuperFastHash

2010-12-23 Thread Gleb Kurtsou
Hi,

I've recently noticed that hash table use in nullfs was inefficient, 1/3
to half of buckets remained unused. I've started investigating it
further and came across SuperFastHash hashing function, SFH
(SuperFastHash) has BSD license, used in WebKit and other open source
projects. Detailed description and Comparision with FNV and Bob Jenkin's
hash can be found here:
http://www.azillionmonkeys.com/qed/hash.html

In my tests SFH (SuperFastHash) was 1.3 to 4 times faster than FNV (it
depends on size of data being hashed) e.g. performance of hashing 56
bytes struct (Core i5 CPU, 2 cores + 2 hyperthreads):
SFH -- 1339.79 MB/s
FNV -- 330.27 MB/s

I've prepared a patch to change FNV and hash32 with SFH in the tree.

For testing I've used dbench with 16 processes on 1 Gb swap back md
device, UFS + SoftUpdates:
Old hash (Mb/s): 599.94  600.096 599.536
SFH hash (Mb/s): 612.439 612.341 609.673

It's just ~1% improvement, but dbench is not a VFS metadata intensive
benchmark. Subjectively it feels faster accessing maildir mailboxes
with ~10.000 messages : )

I'd also wish hash32 (often called Bernstein hash) to be replaced with
better function (it might be FNV if not SFH). Hash32 is inappropriate
for binary data that results in poor distribution.

Thanks,
Gleb.
commit 6e19401826b6769fa95b1e4f9e561dec7101082b
Author: Gleb Kurtsou 
Date:   Thu Dec 16 08:05:14 2010 +0200

Import Paul Hsieh's SuperFastHash.

Replace FNV and Bernstein hash uses with SFH.
In most cases Bernstein is simply inappropriate choice.

diff --git a/lib/libkvm/kvm_minidump_amd64.c b/lib/libkvm/kvm_minidump_amd64.c
index 15630b1..7c9c4dd 100644
--- a/lib/libkvm/kvm_minidump_amd64.c
+++ b/lib/libkvm/kvm_minidump_amd64.c
@@ -35,7 +35,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -74,26 +74,26 @@ static void
 hpt_insert(kvm_t *kd, vm_paddr_t pa, int64_t off)
 {
struct hpte *hpte;
-   uint32_t fnv = FNV1_32_INIT;
+   uint32_t hash;
 
-   fnv = fnv_32_buf(&pa, sizeof(pa), fnv);
-   fnv &= (HPT_SIZE - 1);
+   hash = hash_sfh_buf(&pa, sizeof(pa), sizeof(pa));
+   hash &= (HPT_SIZE - 1);
hpte = malloc(sizeof(*hpte));
hpte->pa = pa;
hpte->off = off;
-   hpte->next = kd->vmst->hpt_head[fnv];
-   kd->vmst->hpt_head[fnv] = hpte;
+   hpte->next = kd->vmst->hpt_head[hash];
+   kd->vmst->hpt_head[hash] = hpte;
 }
 
 static int64_t
 hpt_find(kvm_t *kd, vm_paddr_t pa)
 {
struct hpte *hpte;
-   uint32_t fnv = FNV1_32_INIT;
+   uint32_t hash;
 
-   fnv = fnv_32_buf(&pa, sizeof(pa), fnv);
-   fnv &= (HPT_SIZE - 1);
-   for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next) {
+   hash = hash_sfh_buf(&pa, sizeof(pa), sizeof(pa));
+   hash &= (HPT_SIZE - 1);
+   for (hpte = kd->vmst->hpt_head[hash]; hpte != NULL; hpte = hpte->next) {
if (pa == hpte->pa)
return (hpte->off);
}
diff --git a/lib/libkvm/kvm_minidump_arm.c b/lib/libkvm/kvm_minidump_arm.c
index d48c1bc..f42f4ca 100644
--- a/lib/libkvm/kvm_minidump_arm.c
+++ b/lib/libkvm/kvm_minidump_arm.c
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -77,26 +77,26 @@ static void
 hpt_insert(kvm_t *kd, uint64_t pa, int64_t off)
 {
struct hpte *hpte;
-   uint32_t fnv = FNV1_32_INIT;
+   uint32_t hash;
 
-   fnv = fnv_32_buf(&pa, sizeof(pa), fnv);
-   fnv &= (HPT_SIZE - 1);
+   hash = hash_sfh_buf(&pa, sizeof(pa), sizeof(pa));
+   hash &= (HPT_SIZE - 1);
hpte = malloc(sizeof(*hpte));
hpte->pa = pa;
hpte->off = off;
-   hpte->next = kd->vmst->hpt_head[fnv];
-   kd->vmst->hpt_head[fnv] = hpte;
+   hpte->next = kd->vmst->hpt_head[hash];
+   kd->vmst->hpt_head[hash] = hpte;
 }
 
 static int64_t
 hpt_find(kvm_t *kd, uint64_t pa)
 {
struct hpte *hpte;
-   uint32_t fnv = FNV1_32_INIT;
+   uint32_t hash;
 
-   fnv = fnv_32_buf(&pa, sizeof(pa), fnv);
-   fnv &= (HPT_SIZE - 1);
-   for (hpte = kd->vmst->hpt_head[fnv]; hpte != NULL; hpte = hpte->next)
+   hash = hash_sfh_buf(&pa, sizeof(pa), sizeof(pa));
+   hash &= (HPT_SIZE - 1);
+   for (hpte = kd->vmst->hpt_head[hash]; hpte != NULL; hpte = hpte->next)
if (pa == hpte->pa)
return (hpte->off);
 
diff --git a/lib/libkvm/kvm_minidump_i386.c b/lib/libkvm/kvm_minidump_i386.c
index 0d31705..343d70e 100644
--- a/lib/libkvm/kvm_minidump_i386.c
+++ b/lib/libkvm/kvm_minidump_i386.c
@@ -35,7 +35,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -76,26 +76,26 @@ static void
 hpt_insert(kvm_t *kd, uint64_t pa, int64_t off)
 {
struct hpte *hpte;
-   uint32_t fnv = FNV1_32_INIT;
+   uint32_t hash;
 
-   fnv =