|
6 | 6 | """ |
7 | 7 |
|
8 | 8 | import functools |
9 | | -import hashlib |
10 | | -import struct |
11 | 9 | import threading |
12 | 10 |
|
13 | 11 | from lib.core.datatype import LRUDict |
14 | 12 | from lib.core.settings import MAX_CACHE_ITEMS |
15 | | -from lib.core.settings import UNICODE_ENCODING |
16 | 13 | from lib.core.threads import getCurrentThreadData |
17 | 14 |
|
18 | 15 | _cache = {} |
@@ -40,31 +37,37 @@ def cachedmethod(f): |
40 | 37 | _cache[f] = LRUDict(capacity=MAX_CACHE_ITEMS) |
41 | 38 | _method_locks[f] = threading.RLock() |
42 | 39 |
|
| 40 | + def _freeze(val): |
| 41 | + if isinstance(val, (list, set, tuple)): |
| 42 | + return tuple(_freeze(x) for x in val) |
| 43 | + if isinstance(val, dict): |
| 44 | + return tuple(sorted((k, _freeze(v)) for k, v in val.items())) |
| 45 | + return val |
| 46 | + |
43 | 47 | @functools.wraps(f) |
44 | 48 | def _f(*args, **kwargs): |
| 49 | + lock, cache = _method_locks[f], _cache[f] |
| 50 | + |
45 | 51 | try: |
46 | | - # NOTE: fast-path |
47 | 52 | if kwargs: |
48 | | - key = hash((f, args, tuple(map(type, args)), frozenset(kwargs.items()))) & 0x7fffffffffffffff |
| 53 | + key = (args, frozenset(kwargs.items())) |
49 | 54 | else: |
50 | | - key = hash((f, args, tuple(map(type, args)))) & 0x7fffffffffffffff |
51 | | - except TypeError: |
52 | | - # NOTE: failback slow-path |
53 | | - parts = ( |
54 | | - f.__module__ + "." + f.__name__, |
55 | | - "^".join(repr(a) for a in args), |
56 | | - "^".join("%s=%r" % (k, kwargs[k]) for k in sorted(kwargs)) |
57 | | - ) |
58 | | - try: |
59 | | - key = struct.unpack("<Q", hashlib.md5("`".join(parts).encode(UNICODE_ENCODING)).digest()[:8])[0] & 0x7fffffffffffffff |
60 | | - except (struct.error, ValueError): |
61 | | - return f(*args, **kwargs) |
| 55 | + key = args |
62 | 56 |
|
63 | | - lock, cache = _method_locks[f], _cache[f] |
| 57 | + with lock: |
| 58 | + if key in cache: |
| 59 | + return cache[key] |
64 | 60 |
|
65 | | - with lock: |
66 | | - if key in cache: |
67 | | - return cache[key] |
| 61 | + except TypeError: |
| 62 | + # Note: fallback (slowpath( |
| 63 | + if kwargs: |
| 64 | + key = (_freeze(args), _freeze(kwargs)) |
| 65 | + else: |
| 66 | + key = _freeze(args) |
| 67 | + |
| 68 | + with lock: |
| 69 | + if key in cache: |
| 70 | + return cache[key] |
68 | 71 |
|
69 | 72 | result = f(*args, **kwargs) |
70 | 73 |
|
|
0 commit comments