cpython: d40a65658ff0 (original) (raw)

Mercurial > cpython

changeset 85486:d40a65658ff0

Further reduce the cost of hash collisions by inspecting an additional nearby entry.

Raymond Hettinger python@rcn.com
date Sat, 31 Aug 2013 21:27:08 -0700
parents 4d604f1f0219
children 47ccca4b27ce
files Objects/setobject.c
diffstat 1 files changed, 39 insertions(+), 4 deletions(-)[+] [-] Objects/setobject.c 43

line wrap: on

line diff

--- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -65,10 +65,11 @@ chaining would be substantial (100% with The initial probe index is computed as hash mod the table size. Subsequent probe indices are computed as explained in Objects/dictobject.c. -To improve cache locality, each probe is done in pairs. -After the probe is examined, an adjacent entry is then examined as well. -The likelihood is that an adjacent entry is in the same cache line and -can be examined more cheaply than another probe elsewhere in memory. +To improve cache locality, each probe inspects nearby entries before +moving on to probes elsewhere in memory. Depending on alignment and the +size of a cache line, the nearby entries are cheaper to inspect than +other probes elsewhere in memory. This probe strategy reduces the cost +of hash collisions. All arithmetic on hash should ignore overflow. @@ -130,6 +131,26 @@ set_lookkey(PySetObject *so, PyObject *k if (entry->key == dummy && freeslot == NULL) freeslot = entry;

+ i = i * 5 + perturb + 1; j = i & mask; perturb >>= PERTURB_SHIFT; @@ -190,6 +211,17 @@ set_lookkey_unicode(PySetObject *so, PyO if (entry->key == dummy && freeslot == NULL) freeslot = entry;

+ i = i * 5 + perturb + 1; j = i & mask; perturb >>= PERTURB_SHIFT; @@ -258,6 +290,9 @@ set_insert_clean(PySetObject *so, PyObje entry = &table[j ^ 1]; if (entry->key == NULL) break;