I'm trying to figure out how come the 'in' operator gives better performance than checking if a value is within some intervals bounds.
How come the first piece of code is slower than the second one? Intuitively I would expect the first piece of code to be faster (3 boolean operations + 4 integer comparisons), since it only checks the bounds of each interval for every byte, while the second code will iterate over the entire array of our charset (compare against every integer in an array of length=100).
import random
data = random.randbytes(1000000)
a_lower, a_upper, b_lower, b_upper = (9, 13, 32, 126)
%timeit [((x >= a_lower and x <= a_upper) or (x >= b_lower and x <= b_upper)) for x in data]
results in around 82 ms
import string
import random
data = random.randbytes(1000000)
charset = bytearray(string.printable, "ascii")
%timeit [x in charset for x in data]
results in around 44 ms
I have looked into CPython implementation of bytesarray "in", and it looks like it eventually reaches memchr
The only theory I'm left with, is that the first piece of code might have more function calls within it, and that ends up taking more CPU time than the difference between the number of "basic operations".
I put both functions into the
dismodule to observe the number of operations.which returns this:
From this, it can be seen that function_02 is considerable shorter than function_01. Whilst this does not show exact time itself (there are other factors), it certainly gives a good idea of function with the most operations which is a key factor to time.