From 2efa342323a33bf219f0a0ba51df2adde8ff26be Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 1 Jan 2020 14:53:51 -0700 Subject: [PATCH] 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 --- c/globals.h | 1 - c/intern.c | 129 +++++++++------------------------------------------- 2 files changed, 22 insertions(+), 108 deletions(-) diff --git a/c/globals.h b/c/globals.h index 636f2f2bf7..94b240e65d 100644 --- a/c/globals.h +++ b/c/globals.h @@ -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; diff --git a/c/intern.c b/c/intern.c index c71396ca52..6ade458534 100644 --- a/c/intern.c +++ b/c/intern.c @@ -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];