* Few nips and tucks to hash table

This commit is contained in:
Matthew Honnibal 2014-09-15 05:03:44 +02:00
parent e68a431e5e
commit d235299260
2 changed files with 9 additions and 13 deletions

View File

@ -12,9 +12,8 @@ cdef struct Cell:
cdef class PointerHash: cdef class PointerHash:
cdef size_t size cdef size_t size
cdef size_t filled cdef size_t filled
cdef Cell* _last
cdef Cell* cells cdef Cell* cells
cdef val_t get(self, key_t key) cdef val_t get(self, key_t key) nogil
cdef void set(self, key_t key, val_t value) except * cdef void set(self, key_t key, val_t value) except *
cdef void resize(self, size_t new_size) except * cdef void resize(self, size_t new_size) except *

View File

@ -7,8 +7,8 @@ cdef class PointerHash:
def __cinit__(self, size_t initial_size=8): def __cinit__(self, size_t initial_size=8):
self.size = initial_size self.size = initial_size
self.filled = 0 self.filled = 0
self._last = NULL
# Size must be power of two # Size must be power of two
assert self.size != 0
assert self.size & (self.size - 1) == 0 assert self.size & (self.size - 1) == 0
self.cells = <Cell*>calloc(self.size, sizeof(Cell)) self.cells = <Cell*>calloc(self.size, sizeof(Cell))
@ -24,18 +24,13 @@ cdef class PointerHash:
assert key != 0 and value != 0 assert key != 0 and value != 0
self.set(key, <val_t>value) self.set(key, <val_t>value)
cdef val_t get(self, key_t key): cdef val_t get(self, key_t key) nogil:
cell = _find_cell(self.cells, self.size, key) cdef Cell* cell = _find_cell(self.cells, self.size, key)
self._last = cell
return cell.value return cell.value
cdef void set(self, key_t key, val_t value) except *: cdef void set(self, key_t key, val_t value) except *:
cdef Cell* cell cdef Cell* cell
if self._last != NULL and key == self._last.key: cell = _find_cell(self.cells, self.size, key)
cell = self._last
else:
cell = _find_cell(self.cells, self.size, key)
self._last = NULL
if cell.key == 0: if cell.key == 0:
cell.key = key cell.key = key
self.filled += 1 self.filled += 1
@ -44,6 +39,7 @@ cdef class PointerHash:
self.resize(self.size * 2) self.resize(self.size * 2)
cdef void resize(self, size_t new_size) except *: cdef void resize(self, size_t new_size) except *:
assert new_size != 0
assert (new_size & (new_size - 1)) == 0 # Must be a power of 2 assert (new_size & (new_size - 1)) == 0 # Must be a power of 2
assert self.filled * 4 <= new_size * 3 assert self.filled * 4 <= new_size * 3
@ -65,7 +61,8 @@ cdef class PointerHash:
@cython.cdivision @cython.cdivision
cdef inline Cell* _find_cell(Cell* cells, size_t size, key_t key) nogil: cdef inline Cell* _find_cell(Cell* cells, size_t size, key_t key) nogil:
cdef size_t i = (key % size) # Modulo for powers-of-two via bitwise &
cdef size_t i = (key & (size - 1))
while cells[i].key != 0 and cells[i].key != key: while cells[i].key != 0 and cells[i].key != key:
i = (i + 1) % size i = (i + 1) & (size - 1)
return &cells[i] return &cells[i]