Kaydet (Commit) 7d181596 authored tarafından Guido van Rossum's avatar Guido van Rossum

Rewrote lookmapping() according to suggestions by Jyrki Alakuijala.

üst 3b039faf
...@@ -129,38 +129,88 @@ is a prime number). My choice for incr is somewhat arbitrary. ...@@ -129,38 +129,88 @@ is a prime number). My choice for incr is somewhat arbitrary.
static mappingentry *lookmapping PROTO((mappingobject *, object *, long)); static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
static mappingentry * static mappingentry *
lookmapping(mp, key, hash) lookmapping(mp, key, hash)
register mappingobject *mp; mappingobject *mp;
object *key; object *key;
long hash; long hash;
{ {
register int i, incr; /* Optimizations based on observations by Jyrki Alakuijala
register unsigned long sum = (unsigned long) hash; (paraphrased):
register mappingentry *freeslot = NULL;
register int size = mp->ma_size; - This routine is very heavily used, so should be AFAP
/* We must come up with (i, incr) such that 0 <= i < ma_size (As Fast As Possible).
and 0 < incr < ma_size and both are a function of hash */
i = sum % size; - Most of the time, the first try is a hit or a definite
miss; so postpone the calculation of incr until we know the
first try was a miss.
- Write the loop twice, so we can move the test for
freeslot==NULL out of the loop.
- Write the loop using pointer increments and comparisons
rather than using an integer loop index.
Note that it behooves the compiler to calculate the values
of incr*sizeof(*ep) outside the loops and use this in the
increment of ep. I've reduced the number of register
variables to the two most obvious candidates.
*/
register mappingentry *ep;
mappingentry *end;
register object *ekey;
mappingentry *freeslot;
unsigned long sum;
int incr;
int size;
ep = &mp->ma_table[(unsigned long)hash%mp->ma_size];
ekey = ep->me_key;
if (ekey == NULL)
return ep;
if (ekey == dummy)
freeslot = ep;
else if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
return ep;
else
freeslot = NULL;
size = mp->ma_size;
sum = hash;
do { do {
sum = 3*sum + 1; sum = 3*sum + 1;
incr = sum % size; incr = sum % size;
} while (incr == 0); } while (incr == 0);
for (;;) {
register mappingentry *ep = &mp->ma_table[i]; end = mp->ma_table + size;
if (ep->me_key == NULL) {
if (freeslot != NULL) if (freeslot == NULL) {
return freeslot; for (;;) {
else ep += incr;
if (ep >= end)
ep -= size;
ekey = ep->me_key;
if (ekey == NULL)
return ep; return ep;
} if (ekey == dummy) {
if (ep->me_key == dummy) {
if (freeslot == NULL)
freeslot = ep; freeslot = ep;
break;
}
if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
return ep;
} }
else if (ep->me_hash == hash && }
cmpobject(ep->me_key, key) == 0) {
for (;;) {
ep += incr;
if (ep >= end)
ep -= size;
ekey = ep->me_key;
if (ekey == NULL)
return freeslot;
if (ekey != dummy &&
ep->me_hash == hash && cmpobject(ekey, key) == 0)
return ep; return ep;
}
i = (i + incr) % size;
} }
} }
......
...@@ -129,38 +129,88 @@ is a prime number). My choice for incr is somewhat arbitrary. ...@@ -129,38 +129,88 @@ is a prime number). My choice for incr is somewhat arbitrary.
static mappingentry *lookmapping PROTO((mappingobject *, object *, long)); static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
static mappingentry * static mappingentry *
lookmapping(mp, key, hash) lookmapping(mp, key, hash)
register mappingobject *mp; mappingobject *mp;
object *key; object *key;
long hash; long hash;
{ {
register int i, incr; /* Optimizations based on observations by Jyrki Alakuijala
register unsigned long sum = (unsigned long) hash; (paraphrased):
register mappingentry *freeslot = NULL;
register int size = mp->ma_size; - This routine is very heavily used, so should be AFAP
/* We must come up with (i, incr) such that 0 <= i < ma_size (As Fast As Possible).
and 0 < incr < ma_size and both are a function of hash */
i = sum % size; - Most of the time, the first try is a hit or a definite
miss; so postpone the calculation of incr until we know the
first try was a miss.
- Write the loop twice, so we can move the test for
freeslot==NULL out of the loop.
- Write the loop using pointer increments and comparisons
rather than using an integer loop index.
Note that it behooves the compiler to calculate the values
of incr*sizeof(*ep) outside the loops and use this in the
increment of ep. I've reduced the number of register
variables to the two most obvious candidates.
*/
register mappingentry *ep;
mappingentry *end;
register object *ekey;
mappingentry *freeslot;
unsigned long sum;
int incr;
int size;
ep = &mp->ma_table[(unsigned long)hash%mp->ma_size];
ekey = ep->me_key;
if (ekey == NULL)
return ep;
if (ekey == dummy)
freeslot = ep;
else if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
return ep;
else
freeslot = NULL;
size = mp->ma_size;
sum = hash;
do { do {
sum = 3*sum + 1; sum = 3*sum + 1;
incr = sum % size; incr = sum % size;
} while (incr == 0); } while (incr == 0);
for (;;) {
register mappingentry *ep = &mp->ma_table[i]; end = mp->ma_table + size;
if (ep->me_key == NULL) {
if (freeslot != NULL) if (freeslot == NULL) {
return freeslot; for (;;) {
else ep += incr;
if (ep >= end)
ep -= size;
ekey = ep->me_key;
if (ekey == NULL)
return ep; return ep;
} if (ekey == dummy) {
if (ep->me_key == dummy) {
if (freeslot == NULL)
freeslot = ep; freeslot = ep;
break;
}
if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
return ep;
} }
else if (ep->me_hash == hash && }
cmpobject(ep->me_key, key) == 0) {
for (;;) {
ep += incr;
if (ep >= end)
ep -= size;
ekey = ep->me_key;
if (ekey == NULL)
return freeslot;
if (ekey != dummy &&
ep->me_hash == hash && cmpobject(ekey, key) == 0)
return ep; return ep;
}
i = (i + incr) % size;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment