]> granicus.if.org Git - python/commitdiff
bpo-32422: Reduce lru_cache memory usage (GH-5008)
authorINADA Naoki <methane@users.noreply.github.com>
Mon, 25 Dec 2017 17:03:24 +0000 (02:03 +0900)
committerGitHub <noreply@github.com>
Mon, 25 Dec 2017 17:03:24 +0000 (02:03 +0900)
Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst [new file with mode: 0644]
Modules/_functoolsmodule.c

diff --git a/Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst b/Misc/NEWS.d/next/Library/2017-12-25-20-22-47.bpo-32422.5H3Wq2.rst
new file mode 100644 (file)
index 0000000..5918c32
--- /dev/null
@@ -0,0 +1,2 @@
+``functools.lru_cache`` uses less memory (3 words for each cached key) and
+takes about 1/3 time for cyclic GC.
index a571045bcc75f59b7322487da2d613d13f1dadeb..ff4172d663b65f115e68bb28262c156be2449990 100644 (file)
@@ -677,26 +677,9 @@ typedef struct lru_list_elem {
 static void
 lru_list_elem_dealloc(lru_list_elem *link)
 {
-    _PyObject_GC_UNTRACK(link);
     Py_XDECREF(link->key);
     Py_XDECREF(link->result);
-    PyObject_GC_Del(link);
-}
-
-static int
-lru_list_elem_traverse(lru_list_elem *link, visitproc visit, void *arg)
-{
-    Py_VISIT(link->key);
-    Py_VISIT(link->result);
-    return 0;
-}
-
-static int
-lru_list_elem_clear(lru_list_elem *link)
-{
-    Py_CLEAR(link->key);
-    Py_CLEAR(link->result);
-    return 0;
+    PyObject_Del(link);
 }
 
 static PyTypeObject lru_list_elem_type = {
@@ -720,10 +703,7 @@ static PyTypeObject lru_list_elem_type = {
     0,                                  /* tp_getattro */
     0,                                  /* tp_setattro */
     0,                                  /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
-    0,                                  /* tp_doc */
-    (traverseproc)lru_list_elem_traverse,  /* tp_traverse */
-    (inquiry)lru_list_elem_clear,       /* tp_clear */
+    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
 };
 
 
@@ -959,8 +939,8 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
         }
     } else {
         /* Put result in a new link at the front of the queue. */
-        link = (lru_list_elem *)PyObject_GC_New(lru_list_elem,
-                                                &lru_list_elem_type);
+        link = (lru_list_elem *)PyObject_New(lru_list_elem,
+                                             &lru_list_elem_type);
         if (link == NULL) {
             Py_DECREF(key);
             Py_DECREF(result);
@@ -970,7 +950,6 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
         link->hash = hash;
         link->key = key;
         link->result = result;
-        _PyObject_GC_TRACK(link);
         if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
                                       hash) < 0) {
             Py_DECREF(link);
@@ -1151,7 +1130,8 @@ lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
     lru_list_elem *link = self->root.next;
     while (link != &self->root) {
         lru_list_elem *next = link->next;
-        Py_VISIT(link);
+        Py_VISIT(link->key);
+        Py_VISIT(link->result);
         link = next;
     }
     Py_VISIT(self->maxsize_O);