speed up objlist

Instead of using `%` to compute the index into an oblist, use a power
of 2 for the oblist length and bit masking to compute an index. (Maybe
the old hashing function was bad; the current hashing function should
produce good hash-code variation at the level of bits.) Also, make the
oblist array a little sparser to reduce bucket chaining.

original commit: fb87fcb8e47902b80654789d059a25bd4a7a8def
This commit is contained in:
Matthew Flatt 2020-01-01 14:53:51 -07:00
parent bbbda808e5
commit 2efa342323
2 changed files with 22 additions and 108 deletions

View File

@ -135,7 +135,6 @@ EXTERN struct S_G_struct {
uptr phantom_sizes[static_generation+1];
/* intern.c */
iptr *oblist_length_pointer;
iptr oblist_length;
iptr oblist_count;
bucket **oblist;

View File

@ -23,97 +23,15 @@ static iptr hash_sc PROTO((const string_char *s, iptr n));
static iptr hash_uname PROTO((const string_char *s, iptr n));
static ptr mkstring PROTO((const string_char *s, iptr n));
/* list of some primes to use for oblist sizes */
#if (ptr_bits == 32)
static iptr oblist_lengths[] = {
1031,
2053,
4099,
8209,
16411,
32771,
65537,
131101,
262147,
524309,
1048583,
2097169,
4194319,
8388617,
16777259,
33554467,
67108879,
134217757,
268435459,
536870923,
1073741827,
0};
#endif
#if (ptr_bits == 64)
static iptr oblist_lengths[] = {
1031,
2053,
4099,
8209,
16411,
32771,
65537,
131101,
262147,
524309,
1048583,
2097169,
4194319,
8388617,
16777259,
33554467,
67108879,
134217757,
268435459,
536870923,
1073741827,
2147483659,
4294967311,
8589934609,
17179869209,
34359738421,
68719476767,
137438953481,
274877906951,
549755813911,
1099511627791,
2199023255579,
4398046511119,
8796093022237,
17592186044423,
35184372088891,
70368744177679,
140737488355333,
281474976710677,
562949953421381,
1125899906842679,
2251799813685269,
4503599627370517,
9007199254740997,
18014398509482143,
36028797018963971,
72057594037928017,
144115188075855881,
288230376151711813,
576460752303423619,
1152921504606847009,
2305843009213693967,
4611686018427388039,
0};
#endif
#define OBINDEX(hc, len) ((hc) & ((len) - 1))
#define MIN_OBLIST_LENGTH 4096
void S_intern_init() {
IGEN g;
if (!S_boot_time) return;
S_G.oblist_length_pointer = &oblist_lengths[3];
S_G.oblist_length = *S_G.oblist_length_pointer;
S_G.oblist_length = MIN_OBLIST_LENGTH;
S_G.oblist_count = 0;
S_G.oblist = S_getmem(S_G.oblist_length * sizeof(bucket *), 1);
for (g = 0; g < static_generation; g += 1) S_G.buckets_of_generation[g] = NULL;
@ -146,35 +64,33 @@ static void oblist_insert(ptr sym, iptr idx, IGEN g) {
void S_resize_oblist(void) {
bucket **new_oblist, *b, *oldb, **pb, *bnext;
iptr *new_oblist_length_pointer, new_oblist_length, i, idx;
iptr new_oblist_length, i, idx, inc = 0, dinc = 0;
ptr sym;
IGEN g;
new_oblist_length_pointer = S_G.oblist_length_pointer;
new_oblist_length = MIN_OBLIST_LENGTH;
while ((new_oblist_length >> 1) < S_G.oblist_count)
new_oblist_length <<= 1;
if (S_G.oblist_count < S_G.oblist_length) {
while (new_oblist_length_pointer != &oblist_lengths[0] && *(new_oblist_length_pointer - 1) >= S_G.oblist_count) {
new_oblist_length_pointer -= 1;
}
} else if (S_G.oblist_count > S_G.oblist_length) {
while (*(new_oblist_length_pointer + 1) != 0 && *(new_oblist_length_pointer + 1) <= S_G.oblist_count) {
new_oblist_length_pointer += 1;
}
}
if (new_oblist_length == S_G.oblist_length)
return;
if (new_oblist_length_pointer == S_G.oblist_length_pointer) return;
new_oblist_length = *new_oblist_length_pointer;
new_oblist = S_getmem(new_oblist_length * sizeof(bucket *), 1);
for (i = 0; i < S_G.oblist_length; i += 1) {
for (b = S_G.oblist[i]; b != NULL; b = bnext) {
int done = 0;
bnext = b->next;
sym = b->sym;
idx = UNFIX(SYMHASH(sym)) % new_oblist_length;
idx = OBINDEX(UNFIX(SYMHASH(sym)), new_oblist_length);
g = GENERATION(sym);
for (pb = &new_oblist[idx]; (oldb = *pb) != NULL && SegmentGeneration(addr_get_segment(oldb)) < g; pb = &oldb->next);
for (pb = &new_oblist[idx]; (oldb = *pb) != NULL && SegmentGeneration(addr_get_segment(oldb)) < g; pb = &oldb->next) {
inc++;
if (done)
dinc++;
done = 1;
}
b->next = oldb;
*pb = b;
}
@ -183,7 +99,6 @@ void S_resize_oblist(void) {
S_freemem(S_G.oblist, S_G.oblist_length * sizeof(bucket *));
S_G.bytesof[static_generation][countof_oblist] += (new_oblist_length - S_G.oblist_length) * sizeof(bucket *);
S_G.oblist_length_pointer = new_oblist_length_pointer;
S_G.oblist_length = new_oblist_length;
S_G.oblist = new_oblist;
}
@ -236,7 +151,7 @@ ptr S_mkstring(const string_char *s, iptr n) {
ptr S_intern(const unsigned char *s) {
iptr n = strlen((const char *)s);
iptr hc = hash(s, n);
iptr idx = hc % S_G.oblist_length;
iptr idx = OBINDEX(hc, S_G.oblist_length);
ptr sym;
bucket *b;
@ -272,7 +187,7 @@ ptr S_intern(const unsigned char *s) {
/* handles string_chars, explicit length */
ptr S_intern_sc(const string_char *name, iptr n, ptr name_str) {
iptr hc = hash_sc(name, n);
iptr idx = hc % S_G.oblist_length;
iptr idx = OBINDEX(hc, S_G.oblist_length);
ptr sym;
bucket *b;
@ -309,7 +224,7 @@ ptr S_intern_sc(const string_char *name, iptr n, ptr name_str) {
ptr S_intern3(const string_char *pname, iptr plen, const string_char *uname, iptr ulen, ptr pname_str, ptr uname_str) {
iptr hc = hash_uname(uname, ulen);
iptr idx = hc % S_G.oblist_length;
iptr idx = OBINDEX(hc, S_G.oblist_length);
ptr sym;
bucket *b;
@ -351,7 +266,7 @@ void S_intern_gensym(sym) ptr sym; {
const string_char *uname = &STRIT(uname_str, 0);
iptr ulen = Sstring_length(uname_str);
iptr hc = hash_uname(uname, ulen);
iptr idx = hc % S_G.oblist_length;
iptr idx = OBINDEX(hc, S_G.oblist_length);
bucket *b;
tc_mutex_acquire()
@ -388,7 +303,7 @@ ptr S_intern4(sym) ptr sym; {
const string_char *uname = &STRIT(uname_str, 0);
iptr ulen = Sstring_length(uname_str);
iptr hc = UNFIX(SYMHASH(sym));
iptr idx = hc % S_G.oblist_length;
iptr idx = OBINDEX(hc, S_G.oblist_length);
bucket *b;
b = S_G.oblist[idx];