[svn:parrot] r38383 - trunk/src

chromatic at svn.parrot.org chromatic at svn.parrot.org
Tue Apr 28 02:14:57 UTC 2009


Author: chromatic
Date: Tue Apr 28 02:14:57 2009
New Revision: 38383
URL: https://trac.parrot.org/parrot/changeset/38383

Log:
[src] Added a minor optimization to parrot_hash_get_bucket() to avoid some
expensive hashing and comparisons when it's not necessary.  The sweet spot is
somewhere between four and eight entries in the hash.

Modified:
   trunk/src/hash.c

Modified: trunk/src/hash.c
==============================================================================
--- trunk/src/hash.c	Tue Apr 28 02:12:28 2009	(r38382)
+++ trunk/src/hash.c	Tue Apr 28 02:14:57 2009	(r38383)
@@ -30,6 +30,9 @@
 #include "parrot/parrot.h"
 #include "pmc/pmc_key.h"
 
+/* the number of entries above which it's faster to hash the hashval instead of
+ * looping over the used HashBuckets directly */
+#define SMALL_HASH_SIZE  4
 #define INITIAL_BUCKETS 16
 
 /* HEADERIZER HFILE: include/parrot/hash.h */
@@ -1188,13 +1191,35 @@
 parrot_hash_get_bucket(PARROT_INTERP, ARGIN(const Hash *hash), ARGIN(const void *key))
 {
     ASSERT_ARGS(parrot_hash_get_bucket)
-    if (hash->entries > 0) {
+
+    if (hash->entries <= 0)
+        return NULL;
+
+    /* a very fast search for very small hashes */
+    if (hash->entries <= SMALL_HASH_SIZE) {
+        const UINTVAL  entries = hash->entries;
+        UINTVAL        i;
+
+        for (i = 0; i < entries; i++) {
+            HashBucket *bucket = hash->bs + i;
+
+            /* the hash->compare cost is too high for this fast path */
+            if (bucket->key && bucket->key == key)
+                return bucket;
+        }
+    }
+
+    /* if the fast search didn't work, try the normal hashing search */
+    {
         const UINTVAL hashval = (hash->hash_val)(interp, key, hash->seed);
         HashBucket   *bucket  = hash->bi[hashval & hash->mask];
 
         while (bucket) {
-            /* store hash_val or not */
-            if ((hash->compare)(interp, key, bucket->key) == 0)
+            /* key equality is always a match, so it's worth checking */
+            if (bucket->key == key
+
+            /* ... but the slower comparison is more accurate */
+            || ((hash->compare)(interp, key, bucket->key) == 0))
                 return bucket;
             bucket = bucket->next;
         }


More information about the parrot-commits mailing list