[sgen] Use a power of two as the cement hash size.
authorMark Probst <mark.probst@gmail.com>
Wed, 13 Aug 2014 19:59:24 +0000 (12:59 -0700)
committerMark Probst <mark.probst@gmail.com>
Wed, 13 Aug 2014 20:00:05 +0000 (13:00 -0700)
Cementing, specifically the hashing, showed up when profiling GC heavy
code.  This reduces the footprint.

mono/metadata/sgen-conf.h
mono/metadata/sgen-pinning.c

index f44a4d4ace66c10eae1d458135d1f8e4fe82feb9..009d0f66ee21db9968bac99939eaf4be1a268c74 100644 (file)
@@ -194,16 +194,17 @@ typedef guint64 mword;
 /*
  * Configurable cementing parameters.
  *
- * The hash table size should be a prime.  If there are too many
- * pinned nursery objects with many references from the major heap,
- * this number must be increased.
+ * If there are too many pinned nursery objects with many references
+ * from the major heap, the hash table size must be increased.
  *
  * The threshold is the number of references from the major heap to a
  * pinned nursery object which triggers cementing: if there are more
  * than that number of references, the pinned object is cemented until
  * the next major collection.
  */
-#define SGEN_CEMENT_HASH_SIZE  61
+#define SGEN_CEMENT_HASH_SHIFT 6
+#define SGEN_CEMENT_HASH_SIZE  (1 << SGEN_CEMENT_HASH_SHIFT)
+#define SGEN_CEMENT_HASH(hv)   (((hv) ^ ((hv) >> SGEN_CEMENT_HASH_SHIFT)) & (SGEN_CEMENT_HASH_SIZE - 1))
 #define SGEN_CEMENT_THRESHOLD  1000
 
 #endif
index 85ee6e9f40016398d1d57fc7bc676abfe99e64e3..523c7737b14e4108143c7a45b2f3ca22421cd4ca 100644 (file)
@@ -246,7 +246,8 @@ sgen_cement_concurrent_finish (void)
 gboolean
 sgen_cement_lookup (char *obj)
 {
-       int i = mono_aligned_addr_hash (obj) % SGEN_CEMENT_HASH_SIZE;
+       guint hv = mono_aligned_addr_hash (obj);
+       int i = SGEN_CEMENT_HASH (hv);
 
        SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Looking up cementing for non-nursery objects makes no sense");
 
@@ -264,6 +265,7 @@ sgen_cement_lookup (char *obj)
 gboolean
 sgen_cement_lookup_or_register (char *obj)
 {
+       guint hv;
        int i;
        CementHashEntry *hash;
        gboolean concurrent_cementing = sgen_concurrent_collection_in_progress ();
@@ -279,17 +281,8 @@ sgen_cement_lookup_or_register (char *obj)
        else
                hash = cement_hash;
 
-       /*
-        * We use modulus hashing, which is fine with constants as gcc
-        * can optimize them to multiplication, but with variable
-        * values it would be a bad idea given armv7 has no hardware
-        * for division, making it 20x slower than a multiplication.
-        *
-        * This code path can be quite hot, depending on the workload,
-        * so if we make the hash size user-adjustable we should
-        * figure out something not involving division.
-        */
-       i = mono_aligned_addr_hash (obj) % SGEN_CEMENT_HASH_SIZE;
+       hv = mono_aligned_addr_hash (obj);
+       i = SGEN_CEMENT_HASH (hv);
 
        SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Can only cement pointers to nursery objects");