diff options
author | Guido van Rossum <guido@python.org> | 2020-08-03 16:04:13 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-03 16:04:13 (GMT) |
commit | 488512bf4953d856fcb049a05060a450af52fcdc (patch) | |
tree | 27a37555ebd95259ca97d726fbd5eb3bed1a8b3c /Objects | |
parent | c36dbac588e1d99975f285a874bb20e9f5040af4 (diff) | |
download | cpython-488512bf4953d856fcb049a05060a450af52fcdc.zip cpython-488512bf4953d856fcb049a05060a450af52fcdc.tar.gz cpython-488512bf4953d856fcb049a05060a450af52fcdc.tar.bz2 |
A (very) slight speed improvement for iterating over bytes (#21705)
My mentee @xvxvxvxvxv noticed that iterating over array.array is
slightly faster than iterating over bytes. Looking at the source I
observed that arrayiter_next() calls `getitem(ao, it->index++)` wheras
striter_next() uses the idiom (paraphrased)
item = PyLong_FromLong(seq->ob_sval[it->it_index]);
if (item != NULL)
++it->it_next;
return item;
I'm not 100% sure but I think that the second version has fewer
opportunity for the CPU to overlap the `index++` operation with the
rest of the code (which in both cases involves a call). So here I am
optimistically incrementing the index -- if the PyLong_FromLong() call
fails, this will leave the iterator pointing at the next byte, but
honestly I doubt that anyone would seriously consider resuming use of
the iterator after that kind of failure (it would have to be a
MemoryError). And the author of arrayiter_next() made the same
consideration (or never ever gave it a thought :-).
With this, a loop like
for _ in b: pass
is now slightly *faster* than the same thing over an equivalent array,
rather than slightly *slower* (in both cases a few percent).
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/bytesobject.c | 8 |
1 files changed, 2 insertions, 6 deletions
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 3a922d3..836a736 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3139,7 +3139,6 @@ static PyObject * striter_next(striterobject *it) { PyBytesObject *seq; - PyObject *item; assert(it != NULL); seq = it->it_seq; @@ -3148,11 +3147,8 @@ striter_next(striterobject *it) assert(PyBytes_Check(seq)); if (it->it_index < PyBytes_GET_SIZE(seq)) { - item = PyLong_FromLong( - (unsigned char)seq->ob_sval[it->it_index]); - if (item != NULL) - ++it->it_index; - return item; + return PyLong_FromLong( + (unsigned char)seq->ob_sval[it->it_index++]); } it->it_seq = NULL; |