Skip to content

Commit 4a088f4

Browse files
committed
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.
1 parent a0d3299 commit 4a088f4

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

py/map.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,20 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
127127
mp_map_rehash(map);
128128
// restart the search for the new element
129129
pos = hash % map->alloc;
130+
continue;
130131
} else {
131132
map->used += 1;
132133
elem->key = index;
134+
elem->value = NULL;
133135
if (!MP_OBJ_IS_QSTR(index)) {
134136
map->all_keys_are_qstrs = 0;
135137
}
136138
return elem;
137139
}
138-
} else {
140+
} else if (elem->value == NULL) {
139141
return NULL;
140142
}
143+
// Otherwise it's just entry marked as deleted, so continue with next one
141144
} else if (elem->key == index || (!map->all_keys_are_qstrs && mp_obj_equal(elem->key, index))) {
142145
// found it
143146
/* 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
152155
retval->key = elem->key;
153156
retval->value = elem->value;
154157
elem->key = NULL;
155-
elem->value = NULL;
158+
// elem->key = NULL && elem->value != NULL means "marked deleted"
159+
// assume value indeed never NULL
156160
return retval;
157161
}
158162
return elem;
159-
} else {
160-
// not yet found, keep searching in this table
161-
pos = (pos + 1) % map->alloc;
162163
}
164+
165+
// not yet found, keep searching in this table
166+
pos = (pos + 1) % map->alloc;
163167
}
164168
}
165169

0 commit comments

Comments
 (0)