builtin: map: fix memory leak
parent
31ba64b409
commit
64173c792f
|
@ -40,7 +40,7 @@ metas = [meta, kv_index, 0, 0, meta, kv_index, 0, 0, meta, kv_index, ...]
|
||||||
key_values = [kv, kv, kv, ...]
|
key_values = [kv, kv, kv, ...]
|
||||||
|
|
||||||
4. The size of metas is a power of two. This enables the use of bitwise AND
|
4. The size of metas is a power of two. This enables the use of bitwise AND
|
||||||
to convert the 64-bit hash to a bucket/index that doesn't overflow metas. If
|
to convert the 64-bit hash to a bucket/index that doesn't overflow metas. If
|
||||||
the size is power of two you can use "hash & (SIZE - 1)" instead of "hash %
|
the size is power of two you can use "hash & (SIZE - 1)" instead of "hash %
|
||||||
SIZE". Modulo is extremely expensive so using '&' is a big performance impro-
|
SIZE". Modulo is extremely expensive so using '&' is a big performance impro-
|
||||||
vement. The general concern with this approach is that you only make use of
|
vement. The general concern with this approach is that you only make use of
|
||||||
|
@ -60,7 +60,7 @@ much faster rehashing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Number of bits from the hash stored for each entry
|
// Number of bits from the hash stored for each entry
|
||||||
hashbits = 24
|
hashbits = 24
|
||||||
// Number of bits from the hash stored for rehashing
|
// Number of bits from the hash stored for rehashing
|
||||||
max_cached_hashbits = 16
|
max_cached_hashbits = 16
|
||||||
|
@ -132,7 +132,6 @@ fn (mut d DenseArray) push(key string, value voidptr) u32 {
|
||||||
return push_index
|
return push_index
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private function. Used to implement array[] operator
|
|
||||||
fn (d DenseArray) get(i int) voidptr {
|
fn (d DenseArray) get(i int) voidptr {
|
||||||
$if !no_bounds_checking? {
|
$if !no_bounds_checking? {
|
||||||
if i < 0 || i >= d.size {
|
if i < 0 || i >= d.size {
|
||||||
|
@ -252,6 +251,11 @@ fn (mut m map) meta_greater(_index u32, _metas u32, kvi u32) {
|
||||||
m.metas[index] = meta
|
m.metas[index] = meta
|
||||||
m.metas[index + 1] = kv_index
|
m.metas[index + 1] = kv_index
|
||||||
probe_count := (meta >> hashbits) - 1
|
probe_count := (meta >> hashbits) - 1
|
||||||
|
m.ensure_extra_metas(probe_count)
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (mut m map) ensure_extra_metas(probe_count u32) {
|
||||||
if (probe_count << 1) == m.extra_metas {
|
if (probe_count << 1) == m.extra_metas {
|
||||||
m.extra_metas += extra_metas_inc
|
m.extra_metas += extra_metas_inc
|
||||||
mem_size := (m.cap + 2 + m.extra_metas)
|
mem_size := (m.cap + 2 + m.extra_metas)
|
||||||
|
@ -264,7 +268,8 @@ fn (mut m map) meta_greater(_index u32, _metas u32, kvi u32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut m map) set(key string, value voidptr) {
|
fn (mut m map) set(k string, value voidptr) {
|
||||||
|
key := k.clone()
|
||||||
load_factor := f32(m.size << 1) / f32(m.cap)
|
load_factor := f32(m.size << 1) / f32(m.cap)
|
||||||
if load_factor > max_load_factor {
|
if load_factor > max_load_factor {
|
||||||
m.expand()
|
m.expand()
|
||||||
|
@ -385,6 +390,8 @@ pub fn (mut m map) delete(key string) {
|
||||||
m.size--
|
m.size--
|
||||||
m.metas[index] = 0
|
m.metas[index] = 0
|
||||||
m.key_values.deletes++
|
m.key_values.deletes++
|
||||||
|
// Mark key as deleted
|
||||||
|
m.key_values.keys[kv_index].free()
|
||||||
C.memset(&m.key_values.keys[kv_index], 0, sizeof(string))
|
C.memset(&m.key_values.keys[kv_index], 0, sizeof(string))
|
||||||
if m.key_values.size <= 32 {
|
if m.key_values.size <= 32 {
|
||||||
return
|
return
|
||||||
|
@ -410,7 +417,7 @@ pub fn (m &map) keys() []string {
|
||||||
if m.key_values.keys[i].str == 0 {
|
if m.key_values.keys[i].str == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
keys[j] = m.key_values.keys[i]
|
keys[j] = m.key_values.keys[i].clone()
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
|
|
Loading…
Reference in New Issue