Why single-char slicing on non-ASCII strings is slower?

Viewed 53

Let us consider the following code:

n = 10000000
s1 = 'a' + 'α' * n + 'α' + 'a'
s2 = 'a' + 'a' * n + 'a' + 'a'

So s1 contains non-ASCII characters, while s2 contains strictly ASCII 7-bit characters.


Now, s1 is almost twice as big as s2:

import sys


print(sys.getsizeof(s1), sys.getsizeof(s2))
# 20000080 10000052

If one were to perform arbitrary slicing with the same indexes on these two strings (of same length), it is not surprising that this is slower for s1 as more data is being copied around.

What did surprise me, though, is that if one tries to get the first and last item (which are ASCII 7-bit in both), one gets (slightly) worse performance on s1:

m = 200
%timeit [s1[-1] for _ in range(m)]
# 100000 loops, best of 3: 11.4 µs per loop
%timeit [s2[-1] for _ in range(m)]
# 100000 loops, best of 3: 10.3 µs per loop

%timeit [s1[0] for _ in range(m)]
# 100000 loops, best of 3: 11 µs per loop
%timeit [s2[0] for _ in range(m)]
# 100000 loops, best of 3: 9.89 µs per loop

I find the result of the last test particularly surprising because it seems to me that one could get away with an array offset in both cases, and see no reason for s2 to be faster.


EDIT: to address the concerns related on timings. This is what I get for the single char slicing without list creation:

%timeit s1[-1]
# 10000000 loops, best of 3: 40.6 ns per loop
%timeit s2[-1]
# 10000000 loops, best of 3: 34.5 ns per loop

%timeit s1[0]
# 10000000 loops, best of 3: 38.3 ns per loop
%timeit s2[0]
# 10000000 loops, best of 3: 33.1 ns per loop
0 Answers
Related