]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39028: Performance enhancement in keyword extraction (GH-17576)
authorSebastian Berg <sebastian@sipsolutions.net>
Wed, 18 Dec 2019 06:51:22 +0000 (00:51 -0600)
committerInada Naoki <songofacandy@gmail.com>
Wed, 18 Dec 2019 06:51:22 +0000 (15:51 +0900)
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.

Misc/NEWS.d/next/Core and Builtins/2019-12-17-23-20-51.bpo-39028.SND4TB.rst [new file with mode: 0644]
Python/getargs.c

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 (file)
index 0000000..ee7639e
--- /dev/null
@@ -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
index 351889f8e5189554253f67c1730a388a0a2b3d0c..d5caf47a02838eca733bb0352e3ec309987535a8 100644 (file)
@@ -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];