mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Grow small map entry arrays through 1, 2, 3, 4, 6, 8, 12 and 16 slots (#1688)
This commit is contained in:
@@ -702,11 +702,18 @@ static void scr_map_compact(ScrMap *m, bool reindex) {
|
||||
* range. */
|
||||
#define SCR_MAP_MAX_ENTRIES ((size_t)1 << 30)
|
||||
|
||||
/* The first entry gets an array of one, so a one-entry map keeps no unused
|
||||
* slots; the second grows it to four, and capacity doubles after that. */
|
||||
/* The entry capacity after `cap`: 1, 2, 3, 4, 6, 8, 12, 16, then doubling.
|
||||
* Most maps hold one to four entries, so a small map keeps at most a third
|
||||
* of its slots unused, and appends stay amortized constant. */
|
||||
static size_t scr_map_next_ecap(size_t cap) {
|
||||
if (cap < 4) return cap + 1;
|
||||
if (cap < 16) return cap < 8 ? cap + 2 : cap + 4;
|
||||
return cap * 2;
|
||||
}
|
||||
|
||||
static void scr_map_grow_entries(ScrMap *m) {
|
||||
size_t cap = m->ecap == 0 ? 1 : m->ecap < 4 ? 4 : m->ecap;
|
||||
while (cap < m->nentries + 1) cap *= 2;
|
||||
size_t cap = scr_map_next_ecap(m->ecap);
|
||||
while (cap < m->nentries + 1) cap = scr_map_next_ecap(cap);
|
||||
if (cap > SCR_MAP_MAX_ENTRIES) scr_map_oom();
|
||||
ScrMapEntry *entries = scr_mem_realloc(m->entries, cap * scr_map_entry_size(m));
|
||||
if (!entries) scr_map_oom();
|
||||
|
||||
@@ -242,17 +242,17 @@ static void modes(void) {
|
||||
scr_map_release(set);
|
||||
}
|
||||
|
||||
/* Small maps keep compact storage: the entries array starts with one slot
|
||||
* and grows to four, and maps of up to 8 entries keep no bucket table. */
|
||||
/* Small maps keep compact storage: the entries array grows through 1, 2,
|
||||
* 3, 4, 6 and 8 slots, and maps of up to 8 entries keep no bucket table. */
|
||||
static void small_storage(void) {
|
||||
ScrMap *map = scr_map_new(SCR_MAP_KEY_F64, SCR_MAP_VAL_F64, NULL);
|
||||
assert(!map->entries && map->ecap == 0);
|
||||
scr_map_set_f64_f64(map, 100000, 1);
|
||||
assert(map->ecap == 1);
|
||||
scr_map_set_f64_f64(map, 200000, 2);
|
||||
assert(map->ecap == 4);
|
||||
for (int i = 3; i <= 8; i++) scr_map_set_f64_f64(map, i * 100000.0, i);
|
||||
assert(map->ecap == 8 && !map->nbuckets && !map->ndense);
|
||||
static const uint32_t caps[] = {1, 2, 3, 4, 6, 6, 8, 8};
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
scr_map_set_f64_f64(map, i * 100000.0, i);
|
||||
assert(map->ecap == caps[i - 1]);
|
||||
}
|
||||
assert(!map->nbuckets && !map->ndense);
|
||||
double out;
|
||||
for (int i = 1; i <= 8; i++) assert(scr_map_get_f64_f64(map, i * 100000.0, &out) && out == i);
|
||||
assert(!scr_map_has_f64(map, 50000) && !scr_map_has_f64(map, 0));
|
||||
|
||||
Reference in New Issue
Block a user