From 75bb07e92baa7267a61056d03d7e6b475588e793 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 18 Dec 2019 00:51:22 -0600 Subject: bpo-39028: Performance enhancement in keyword extraction (GH-17576) All keywords should first be checked for pointer identity. Only after that failed for all keywords (unlikely) should unicode equality be used. The original code would call unicode equality on any non-matching keyword argument. Meaning calling it often e.g. when a function has many kwargs but only the last one is provided. --- .../Core and Builtins/2019-12-17-23-20-51.bpo-39028.SND4TB.rst | 1 + Python/getargs.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2019-12-17-23-20-51.bpo-39028.SND4TB.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-17-23-20-51.bpo-39028.SND4TB.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-17-23-20-51.bpo-39028.SND4TB.rst new file mode 100644 index 0000000..ee7639e --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-12-17-23-20-51.bpo-39028.SND4TB.rst @@ -0,0 +1 @@ +Slightly improve the speed of keyword argument parsing with many kwargs by strengthening the assumption that kwargs are interned strings. \ No newline at end of file diff --git a/Python/getargs.c b/Python/getargs.c index 351889f..d5caf47 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2053,14 +2053,18 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) Py_ssize_t i, nkwargs; nkwargs = PyTuple_GET_SIZE(kwnames); - for (i=0; i < nkwargs; i++) { + for (i = 0; i < nkwargs; i++) { PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); - /* ptr==ptr should match in most cases since keyword keys - should be interned strings */ + /* kwname == key will normally find a match in since keyword keys + should be interned strings; if not retry below in a new loop. */ if (kwname == key) { return kwstack[i]; } + } + + for (i = 0; i < nkwargs; i++) { + PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); assert(PyUnicode_Check(kwname)); if (_PyUnicode_EQ(kwname, key)) { return kwstack[i]; -- cgit v0.12