velocity wrote:I optimized it a bit further by using
Syntax: Select all
if address not in dict: #..code#
instead of
, this is actually slower than 'not in' lookup, because it takes time to lookup the get attribute first. Even so, I have to do a second comparison anyways (if key is not None). At least according to this
https://stackoverflow.com/questions/39582115/python-dictionary-lookup-performance-get-vs-in. I also did run some tests myself.
Tests:
Syntax: Select all
from time import time
A = {'a':0, 'b':0, 'c':0}
b = 'd'
t = time()
for _ in range(10000000):
if b not in A:
continue
result = A[b]
print(time()-t)
t = time()
for _ in range(10000000):
result = A.get(b, None)
if result is None:
continue
print(time()-t)
.get() = 0.6377964019775391s
not in = 1.6540522575378418s
While this is true for when the key doesn't exist, you end up querying it twice for when it does because
dict.__contains__ resolve the value associated with the key to check its presence, and then you retrieve it again through
dict.__getitem__. The length of your dictionary will also affect the lookup speed, and while it may be faster for a dictionary that only contains 3 keys, you will get different result for a larger container. To be fair, you should rather use a
try/
except and catch
KeyError which would be the fastest approach because the chance your hook gets called with an invalid pointer you don't have in your container is statically next to null since you keep it synced at all time. Just for science, take a look at this:
Syntax: Select all
from time import time
from random import randint
d = dict()
for i in range(2048):
k = randint(0, 2147483647)
d[k] = i
print('Key exists:')
t = time()
for i in range(10000000):
if k not in d:
continue
v = d[k]
print('\tIN:', time() - t)
t = time()
for i in range(10000000):
v = d.get(k, None)
print('\tGET:', time() - t)
t = time()
for i in range(10000000):
try:
v = d[k]
except KeyError:
continue
print('\tTRY:', time() - t)
print('Key does not exists:')
k = 'foo'
t = time()
for i in range(10000000):
if k not in d:
continue
v = d[k]
print('\tIN:', time() - t)
t = time()
for i in range(10000000):
v = d.get(k, None)
print('\tGET:', time() - t)
t = time()
for i in range(10000000):
try:
v = d[k]
except KeyError:
continue
print('\tTRY:', time() - t)
Code: Select all
Key exists:
IN: 1.5538604259490967
GET: 1.5824986934661865
TRY: 1.0551846027374268
Key does not exists:
IN: 0.8257911205291748
GET: 1.8011598587036133
TRY: 3.390928030014038
velocity wrote:Is it possible for this function to be implemented in C++? What you guys think. Right now it is just impossible to use in sourcepython.
I'm personally not opposed to it, except maybe for the fact it adds an additional signature to maintain for all games. But other than that, please feel free to make a PR.