1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/builtin/hashmap.v
Alexander Medvednikov 52c2fa44b8 runtime: nr_cpus()
2019-10-11 13:47:56 +03:00

83 lines
1.7 KiB
V

// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module builtin
/*
This is work in progress.
A very early test version of the hashmap with a fixed size.
Only works with string keys and int values for now.
I added this to improve performance of the V compiler,
which uses lots of O(log n) map get's. Turned out with N < 10 000
the performance gains are basically non-existent.
*/
struct hashmap {
cap int
keys []string
table []hashmapentry
elm_size int
pub:
nr_collisions int
}
struct hashmapentry {
key string
val int
next &hashmapentry // linked list for collisions
}
const (
min_cap = 2 << 10
max_cap = 2 << 20
)
fn new_hashmap(planned_nr_items int) hashmap {
mut cap := planned_nr_items * 5
if cap < min_cap {
cap = min_cap
}
if cap > max_cap {
cap = max_cap
}
return hashmap{
cap: cap
elm_size: 4
table: make(cap, cap, sizeof(hashmapentry))
}
}
fn (m mut hashmap) set(key string, val int) {
mut hash := int(b_fabs( key.hash() ))
idx := hash % m.cap
if m.table[idx].key.len != 0 {
//println('\nset() idx=$idx key="$key" hash="$hash" val=$val')
m.nr_collisions++
//println('collision:' + m.table[idx].key)
mut e := &m.table[idx]
for e.next != 0 {
e = e.next
}
e.next = &hashmapentry{key, val, 0}
} else {
m.table[idx] = hashmapentry{key, val, 0}
}
}
fn (m mut hashmap) get(key string) int {
hash := int(b_fabs( key.hash() ))
idx := hash % m.cap
mut e := &m.table[idx]
for e.next != 0 { // todo unsafe {
if e.key == key {
return e.val
}
e = e.next
}
return e.val
}
[inline] fn b_fabs(v int) f64 { return if v < 0 { -v } else { v } }