-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
gh-139476: Optimize range[:]
slice
#139556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
I would instead have a look at how we optimize tuple slicing. strings and tuples check if the result slice would be equivalent to } else if (start == 0 && step == 1 &&
slicelength == PyUnicode_GET_LENGTH(self)) {
return unicode_result_unchanged(self); If you were to make this change with this improved version, then we should also test non-trivial steps and decreasing sequences, as well as empty ones. Otherwise, please add a comment saying that we only optimize |
How about the slightly convoluted, though covering several more cases: if ((slice->start == Py_None || (PyLong_Check(slice->start) && PyLong_AsLong(slice->start) == 0))
&& (slice->stop == Py_None || (PyLong_Check(slice->stop) && PyObject_RichCompareBool(slice->stop, r->length, Py_EQ) == 1))
&& (slice->step == Py_None || (PyLong_Check(slice->step) && PyLong_AsLong(slice->step) == 1)))
{
return Py_NewRef(r);
} Benchmarks(Negligible differences for non-optimised cases, mean of one million runs)
|
Why complicate this. Can't you use |
Same situation with the benchmarks, albeit slightly slower now for the special cases, down to ~3x faster. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still unsure whether this is really needed.
if (start == _PyLong_GetZero() | ||
&& step == _PyLong_GetOne() | ||
&& (slice->stop == Py_None || PyObject_RichCompareBool(stop, r->length, Py_EQ) == 1)) | ||
{ | ||
return Py_NewRef(r); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PyObject_RichCompareBool
can raise an error. Handling it would then make the code more complex. So I'm rather against that change as it's not so trivial.
Also, start == _PyLong_GetZero()
is not correct because it's not guaranteed that 0 will always be immortal (though it should in general and I see that there is code that is doing this for 1). I actually thought that we had the indices as C integers and not Python ones, but it appears that it's not the case.
I have the same sentiment, I think the two best options are closing this or just implementing the initial small patch. |
I will close this one as |
Quick little patch. Optimises the
r[:]
case nicely (~5x), with negligible impact on other cases (I assume it is just noise):r[:]
r[1:]
r[:-1]
r[1:10]
r[::2]
r[1:50:3]
I agree with Benedikt optimising this in general has little benefit, though I think one special case is acceptable. To cover all cases, it would require comparing the objects, resulting in a ~4x performance penalty and or some convoluted code.
tuple
andstr
torange
#139476