[Python-checkins] bpo-30156: Remove property_descr_get() optimization (GH-9541)

Victor Stinner webhook-mailer at python.org
Mon Oct 1 06:03:27 EDT 2018


https://github.com/python/cpython/commit/e972c13624c32d0efdceb08ff83917fb6b488525
commit: e972c13624c32d0efdceb08ff83917fb6b488525
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018-10-01T03:03:22-07:00
summary:

bpo-30156: Remove property_descr_get() optimization (GH-9541)

property_descr_get() uses a "cached" tuple to optimize function
calls. But this tuple can be discovered in debug mode with
sys.getobjects(). Remove the optimization, it's not really worth it
and it causes 3 different crashes last years.

Microbenchmark:

./python -m perf timeit -v \
    -s "from collections import namedtuple; P = namedtuple('P', 'x y'); p = P(1, 2)" \
    --duplicate 1024 "p.x"

Result:

Mean +- std dev: [ref] 32.8 ns +- 0.8 ns -> [patch] 40.4 ns +- 1.3 ns: 1.23x slower (+23%)

files:
A Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst
M Objects/descrobject.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst b/Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst
new file mode 100644
index 000000000000..7086ff4e2d99
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-09-24-17-51-15.bpo-30156.pH0j5j.rst	
@@ -0,0 +1,4 @@
+The C function ``property_descr_get()`` uses a "cached" tuple to optimize
+function calls. But this tuple can be discovered in debug mode with
+:func:`sys.getobjects()`. Remove the optimization, it's not really worth it
+and it causes 3 different crashes last years.
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index b1bee904ec86..82afa8c63f86 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1331,42 +1331,19 @@ property_dealloc(PyObject *self)
 static PyObject *
 property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
 {
-    static PyObject * volatile cached_args = NULL;
-    PyObject *args;
-    PyObject *ret;
-    propertyobject *gs = (propertyobject *)self;
-
     if (obj == NULL || obj == Py_None) {
         Py_INCREF(self);
         return self;
     }
+
+    propertyobject *gs = (propertyobject *)self;
     if (gs->prop_get == NULL) {
         PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
         return NULL;
     }
-    args = cached_args;
-    cached_args = NULL;
-    if (!args) {
-        args = PyTuple_New(1);
-        if (!args)
-            return NULL;
-        _PyObject_GC_UNTRACK(args);
-    }
-    Py_INCREF(obj);
-    PyTuple_SET_ITEM(args, 0, obj);
-    ret = PyObject_Call(gs->prop_get, args, NULL);
-    if (cached_args == NULL && Py_REFCNT(args) == 1) {
-        assert(PyTuple_GET_SIZE(args) == 1);
-        assert(PyTuple_GET_ITEM(args, 0) == obj);
-        cached_args = args;
-        Py_DECREF(obj);
-    }
-    else {
-        assert(Py_REFCNT(args) >= 1);
-        _PyObject_GC_TRACK(args);
-        Py_DECREF(args);
-    }
-    return ret;
+
+    PyObject *args[1] = {obj};
+    return _PyObject_FastCall(gs->prop_get, args, 1);
 }
 
 static int



More information about the Python-checkins mailing list