Skip to content

Instantly share code, notes, and snippets.

@doctaphred
Created October 23, 2020 19:44
Show Gist options
  • Save doctaphred/60540fbf429248b5c99b846b434141a5 to your computer and use it in GitHub Desktop.
Save doctaphred/60540fbf429248b5c99b846b434141a5 to your computer and use it in GitHub Desktop.
"Yo dawg, I heard you like caching..."
from functools import lru_cache
from types import FunctionType
def cache(func):
return lru_cache(maxsize=None)(func)
class Vector(tuple):
# [small brain]
def __add__(self, other):
return type(self)(s + o for s, o in zip(self, other))
class CachedVector(Vector):
# [bigger brain]
__add__ = cache(Vector.__add__)
__repr__ = cache(Vector.__repr__)
class Key:
# [expanding brain]
def __init_subclass__(cls, /, type, **kwargs):
for name, attr in vars(cls).items():
if isinstance(attr, FunctionType):
setattr(cls, name, cache(attr))
cls._type = type
cls._keys = {}
cls._values = {}
def __new__(cls, /, *args, **kwargs):
value = cls._type(*args, **kwargs)
try:
return cls._keys[value]
except KeyError:
key = cls._keys[value] = super().__new__(cls)
cls._values[key] = value
return key
def __call__(self):
return self._values[self]
class VectorKey(Key, type=Vector):
# [galaxy brain]
def __add__(self, other):
return type(self)(self() + other())
def __repr__(self):
return repr(self())
def test(size):
v = Vector(range(size))
c = CachedVector(range(size))
k = VectorKey(range(size))
assert v == c == k()
assert repr(v) == repr(c) == repr(k)
assert (v + v) == (c + c) == (k() + k()) == (k + k)()
assert type(v + v) is Vector
assert type(c + c) is CachedVector
assert type(k + k) is VectorKey
assert type(k() + k()) is Vector
assert type((k + k)()) is Vector
print()
print(f'repr (size {size})')
%timeit repr(v)
%timeit repr(c)
%timeit repr(k)
print()
print(f'str (size {size})')
%timeit str(v)
%timeit str(c)
%timeit str(k)
print()
print(f'== (size {size})')
%timeit v == v
%timeit c == c
%timeit k == k
print()
print(f'+ (size {size})')
%timeit v + v
%timeit c + c
%timeit k + k
%timeit (k + k)()
if __name__ == '__main__':
test(1000)
test(100)
test(10)
test(1)
@doctaphred
Copy link
Author

Preliminary results:

repr (size 1000)
82.9 µs ± 1.11 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
3.15 µs ± 275 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
155 ns ± 1.63 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
str (size 1000)
82.5 µs ± 747 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
3.03 µs ± 86 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
215 ns ± 3.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
== (size 1000)
1.85 µs ± 48 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.81 µs ± 15.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
46.6 ns ± 0.417 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
+ (size 1000)
77.8 µs ± 5.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
5.68 µs ± 67.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
145 ns ± 1.85 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
271 ns ± 3.16 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

repr (size 100)
8.63 µs ± 154 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
432 ns ± 6.74 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
152 ns ± 1.62 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
str (size 100)
8.64 µs ± 279 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
485 ns ± 1.42 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
220 ns ± 7.25 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
== (size 100)
231 ns ± 2.79 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
233 ns ± 5.89 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
47.5 ns ± 1.13 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
+ (size 100)
7.86 µs ± 80 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
750 ns ± 35.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
146 ns ± 3.72 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
283 ns ± 16.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

repr (size 10)
978 ns ± 31.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
177 ns ± 4.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
151 ns ± 6.62 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
str (size 10)
1.05 µs ± 21.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
248 ns ± 13.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
208 ns ± 2.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
== (size 10)
57.8 ns ± 0.381 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
61.1 ns ± 0.303 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
45.8 ns ± 1.68 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
+ (size 10)
1.34 µs ± 62.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
195 ns ± 5.28 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
140 ns ± 2.46 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
269 ns ± 13.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

repr (size 1)
254 ns ± 2.85 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
149 ns ± 0.48 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
146 ns ± 1.32 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
str (size 1)
316 ns ± 3.94 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
211 ns ± 2.13 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
205 ns ± 1.18 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
== (size 1)
42.6 ns ± 0.324 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
46.4 ns ± 0.411 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
44.5 ns ± 0.325 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
+ (size 1)
792 ns ± 9.84 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
144 ns ± 0.374 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
138 ns ± 1.19 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
262 ns ± 3.33 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment