bpo-37207: Use PEP 590 vectorcall to speed up range(), list() and dict() by about 30%#13930
bpo-37207: Use PEP 590 vectorcall to speed up range(), list() and dict() by about 30%#13930markshannon wants to merge 10 commits intopython:masterfrom
Conversation
|
|
Objects/dictobject.c
Outdated
There was a problem hiding this comment.
I don't think there should be a newline right after the (.
Objects/call.c
Outdated
There was a problem hiding this comment.
This change may or may not make sense, but in any case I think that it needs to be justified individually and a test added, preferably on a separate PR.
There was a problem hiding this comment.
The comment in Include/cpython/abstract.h says that _PyStack_UnpackDict does not check the type of keyword arguments. So this change is inconsistent with that. If you think that this should be changed, please open a separate issue explaining the rationale for this change.
There was a problem hiding this comment.
The additional validation should have been in PyVectorcall_Call which does need to do validation. I've moved it there.
There was a problem hiding this comment.
I still think that it's better to move that change to a different PR with rationale explained for this change.
|
Do you have an idea why this speeds up those calls that much? I'm just wondering if we could instead try to optimize the existing code path instead of implementing a mostly duplicate code path. |
|
What are your plans for inheritance of |
jdemeyer
left a comment
There was a problem hiding this comment.
I agree with the overall approach here. However I have various minor comments (some already mentioned):
- I'm not convinced that vectorcall should be used for
dict(). There was a discussion about usingMETH_FASTCALLfordict.update()in bpo-29312 and the conclusion was that it was a bad idea. So either we need to argue that the conclusion on bpo-29312 was wrong or that it doesn't apply to thedict()constructor. - You should try to minimize duplication of functionality. For example
range_newandrange_vectorcallserve essentially the same purpose, so why are there two functions? You could implement both in terms of a common function or implementrange_newas
static PyObject *
range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
if (kw && PyDict_GET_SIZE(kw) != 0) {
PyErr_Format(PyExc_TypeError, "range() takes no keyword arguments");
return NULL;
}
return range_vectorcall(type, _PyTuple_ITEMS(args),
PyTuple_GET_SIZE(args), NULL);
}- Use
Py_ssize_tfor thenargsvariable. - The change to
PyVectorcall_Calldoes not belong here. Please open a separate PR for that. - I'm getting a compiler warning
Objects/rangeobject.c:765:26: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
.tp_vectorcall = range_vectorcall
^~~~~~~~~~~~~~~~
|
Since |
|
dict and dict.update are different. |
|
@methane, I don't understand which point you are trying to make. Right now, there is a common implementation of |
|
I opened https://bugs.python.org/issue37540 for the issue of checking that keyword names are strings. |
Base PR for other PRs that want to play with `type.__call__` such as #13930 and #14589. The author is really @markshannon I just made the PR. https://bugs.python.org/issue37207 Automerge-Triggered-By: @encukou
Base PR for other PRs that want to play with `type.__call__` such as python#13930 and python#14589. The author is really @markshannon I just made the PR. https://bugs.python.org/issue37207 Automerge-Triggered-By: @encukou
…ch previous error messages.
4671080 to
fec6969
Compare
|
It would make sense to delegate tp_call for |
fec6969 to
c319141
Compare
| { | ||
| type->tp_flags |= _Py_TPFLAGS_HAVE_VECTORCALL; | ||
| /* Also inherit tp_vectorcall if tp_call of the | ||
| * metaclass is type.__call__ */ |
There was a problem hiding this comment.
| * metaclass is type.__call__ */ | |
| * metaclass is type.__call__ */ |
| if (nargs == 1) { | ||
| int err = 0; | ||
| PyObject *arg = args[0]; | ||
| _Py_IDENTIFIER(keys); |
There was a problem hiding this comment.
I don't like two same identifiers in single source file.
Please make _Py_IDENTIFIER(keys); global static variable.
Base PR for other PRs that want to play with `type.__call__` such as python#13930 and python#14589. The author is really @markshannon I just made the PR. https://bugs.python.org/issue37207 Automerge-Triggered-By: @encukou
|
This PR has 4 relatively independent parts, and all of it seems stuck on one of them. I opened #18464 to get |
This continues the `range()` part of #13930. The complete pull request is stalled on discussions around dicts, but `range()` should not be controversial. (And I plan to open PRs for other parts if this is merged.) On top of Mark's change, I unified `range_new` and `range_vectorcall`, which had a lot of duplicate code. https://bugs.python.org/issue37207
|
This PR was splitted into multiple smaller PRs which all are now all merged: see https://bugs.python.org/issue37207 |
Base PR for other PRs that want to play with `type.__call__` such as python#13930 and python#14589. The author is really @markshannon I just made the PR. https://bugs.python.org/issue37207 Automerge-Triggered-By: @encukou
https://bugs.python.org/issue37207