Commit 4a088f4b authored by Paul Sokolovsky's avatar Paul Sokolovsky
Browse files

map: When removing a key, don't NULL the entry, but mark as deleted.

When searching next time, such entry should be just skipped, not terminate
the search. It's known that marking techique is not efficient at the presense
of many removes, but namespace usage should not require many deletes, and
as for user dictionaries - well, open addressing map table with linear
rehashing and load factor of ~1 is not particularly efficient at all ;-).
TODO: May consider "shift other entries in cluster" approach as an
alternative.
parent a0d32991
...@@ -127,17 +127,20 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t ...@@ -127,17 +127,20 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
mp_map_rehash(map); mp_map_rehash(map);
// restart the search for the new element // restart the search for the new element
pos = hash % map->alloc; pos = hash % map->alloc;
continue;
} else { } else {
map->used += 1; map->used += 1;
elem->key = index; elem->key = index;
elem->value = NULL;
if (!MP_OBJ_IS_QSTR(index)) { if (!MP_OBJ_IS_QSTR(index)) {
map->all_keys_are_qstrs = 0; map->all_keys_are_qstrs = 0;
} }
return elem; return elem;
} }
} else { } else if (elem->value == NULL) {
return NULL; return NULL;
} }
// Otherwise it's just entry marked as deleted, so continue with next one
} else if (elem->key == index || (!map->all_keys_are_qstrs && mp_obj_equal(elem->key, index))) { } else if (elem->key == index || (!map->all_keys_are_qstrs && mp_obj_equal(elem->key, index))) {
// found it // found it
/* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
...@@ -152,14 +155,15 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t ...@@ -152,14 +155,15 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
retval->key = elem->key; retval->key = elem->key;
retval->value = elem->value; retval->value = elem->value;
elem->key = NULL; elem->key = NULL;
elem->value = NULL; // elem->key = NULL && elem->value != NULL means "marked deleted"
// assume value indeed never NULL
return retval; return retval;
} }
return elem; return elem;
} else {
// not yet found, keep searching in this table
pos = (pos + 1) % map->alloc;
} }
// not yet found, keep searching in this table
pos = (pos + 1) % map->alloc;
} }
} }
......
Supports Markdown
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