-
Notifications
You must be signed in to change notification settings - Fork 550
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor udp.sendto() and pyaddr->sockaddr conversion
* sendto() now tries to use uv_udp_try_send() first * __convert_pyaddr_to_sockaddr() was optimized to maintain an internal LRU cache of resolved addresses (quite an expensive operation)
- Loading branch information
Showing
8 changed files
with
181 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
cdef object _LRU_MARKER = object() | ||
|
||
|
||
@cython.final | ||
cdef class LruCache: | ||
|
||
cdef: | ||
object _dict | ||
int _maxsize | ||
object _dict_move_to_end | ||
object _dict_get | ||
|
||
# We use an OrderedDict for LRU implementation. Operations: | ||
# | ||
# * We use a simple `__setitem__` to push a new entry: | ||
# `entries[key] = new_entry` | ||
# That will push `new_entry` to the *end* of the entries dict. | ||
# | ||
# * When we have a cache hit, we call | ||
# `entries.move_to_end(key, last=True)` | ||
# to move the entry to the *end* of the entries dict. | ||
# | ||
# * When we need to remove entries to maintain `max_size`, we call | ||
# `entries.popitem(last=False)` | ||
# to remove an entry from the *beginning* of the entries dict. | ||
# | ||
# So new entries and hits are always promoted to the end of the | ||
# entries dict, whereas the unused one will group in the | ||
# beginning of it. | ||
|
||
def __init__(self, *, maxsize): | ||
if maxsize <= 0: | ||
raise ValueError( | ||
f'maxsize is expected to be greater than 0, got {maxsize}') | ||
|
||
self._dict = col_OrderedDict() | ||
self._dict_move_to_end = self._dict.move_to_end | ||
self._dict_get = self._dict.get | ||
self._maxsize = maxsize | ||
|
||
cdef get(self, key, default): | ||
o = self._dict_get(key, _LRU_MARKER) | ||
if o is _LRU_MARKER: | ||
return default | ||
self._dict_move_to_end(key) # last=True | ||
return o | ||
|
||
cdef inline needs_cleanup(self): | ||
return len(self._dict) > self._maxsize | ||
|
||
cdef inline cleanup_one(self): | ||
k, _ = self._dict.popitem(last=False) | ||
return k | ||
|
||
def __getitem__(self, key): | ||
o = self._dict[key] | ||
self._dict_move_to_end(key) # last=True | ||
return o | ||
|
||
def __setitem__(self, key, o): | ||
if key in self._dict: | ||
self._dict[key] = o | ||
self._dict_move_to_end(key) # last=True | ||
else: | ||
self._dict[key] = o | ||
while self.needs_cleanup(): | ||
self.cleanup_one() | ||
|
||
def __delitem__(self, key): | ||
del self._dict[key] | ||
|
||
def __contains__(self, key): | ||
return key in self._dict | ||
|
||
def __len__(self): | ||
return len(self._dict) | ||
|
||
def __iter__(self): | ||
return iter(self._dict) |