Index: Objects/dictobject.c =================================================================== --- Objects/dictobject.c (révision 86449) +++ Objects/dictobject.c (copie de travail) @@ -28,8 +28,10 @@ /* Define this out if you don't want conversion statistics on exit. */ #undef SHOW_CONVERSION_COUNTS -/* See large comment block below. This must be >= 1. */ -#define PERTURB_SHIFT 5 +/* Initial hash perturbation, to avoid clustering effects with the master + hash() function while maintaining linear probing for better cache locality + when collision happen. */ +#define INITIAL_HASH(mp, h) (((size_t) h * 1000003) & mp->ma_mask) /* Major subtleties ahead: Most hash schemes depend on having a "good" hash @@ -312,7 +314,6 @@ lookdict(PyDictObject *mp, PyObject *key, register Py_hash_t hash) { register size_t i; - register size_t perturb; register PyDictEntry *freeslot; register size_t mask = (size_t)mp->ma_mask; PyDictEntry *ep0 = mp->ma_table; @@ -320,7 +321,7 @@ register int cmp; PyObject *startkey; - i = (size_t)hash & mask; + i = INITIAL_HASH(mp, hash); ep = &ep0[i]; if (ep->me_key == NULL || ep->me_key == key) return ep; @@ -353,8 +354,8 @@ /* In the loop, me_key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; + for (;;) { + i = i + 1; ep = &ep0[i & mask]; if (ep->me_key == NULL) return freeslot == NULL ? ep : freeslot; @@ -401,7 +402,6 @@ lookdict_unicode(PyDictObject *mp, PyObject *key, register Py_hash_t hash) { register size_t i; - register size_t perturb; register PyDictEntry *freeslot; register size_t mask = (size_t)mp->ma_mask; PyDictEntry *ep0 = mp->ma_table; @@ -418,7 +418,7 @@ mp->ma_lookup = lookdict; return lookdict(mp, key, hash); } - i = hash & mask; + i = INITIAL_HASH(mp, hash); ep = &ep0[i]; if (ep->me_key == NULL || ep->me_key == key) return ep; @@ -432,8 +432,8 @@ /* In the loop, me_key == dummy is by far (factor of 100s) the least likely outcome, so test for that last. */ - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; + for (;;) { + i = i + 1; ep = &ep0[i & mask]; if (ep->me_key == NULL) return freeslot == NULL ? ep : freeslot; @@ -566,16 +566,15 @@ PyObject *value) { register size_t i; - register size_t perturb; register size_t mask = (size_t)mp->ma_mask; PyDictEntry *ep0 = mp->ma_table; register PyDictEntry *ep; MAINTAIN_TRACKING(mp, key, value); - i = hash & mask; + i = INITIAL_HASH(mp, hash); ep = &ep0[i]; - for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; + while (ep->me_key != NULL) { + i = i + 1; ep = &ep0[i & mask]; } assert(ep->me_value == NULL); @@ -825,7 +824,7 @@ */ if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2)) return 0; - return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used); + return dictresize(mp, 2 * mp->ma_used); } int