https://github.com/python/cpython/commit/29772b0647519254b94bdf82df1666e98c3de3a2
commit: 29772b0647519254b94bdf82df1666e98c3de3a2
branch: main
author: Pieter Eendebak <pieter.eende...@gmail.com>
committer: Fidget-Spinner <kenjin4...@gmail.com>
date: 2025-04-05T23:51:05+08:00
summary:

gh-126703: Add PyCFunction freelist (GH-128692)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
M Include/internal/pycore_freelist_state.h
M Objects/methodobject.c
M Objects/object.c

diff --git a/Include/internal/pycore_freelist_state.h 
b/Include/internal/pycore_freelist_state.h
index 7c252f5b570c13..54415b22fd41ef 100644
--- a/Include/internal/pycore_freelist_state.h
+++ b/Include/internal/pycore_freelist_state.h
@@ -24,6 +24,8 @@ extern "C" {
 #  define Py_futureiters_MAXFREELIST 255
 #  define Py_object_stack_chunks_MAXFREELIST 4
 #  define Py_unicode_writers_MAXFREELIST 1
+#  define Py_pycfunctionobject_MAXFREELIST 16
+#  define Py_pycmethodobject_MAXFREELIST 16
 #  define Py_pymethodobjects_MAXFREELIST 20
 
 // A generic freelist of either PyObjects or other data structures.
@@ -53,6 +55,8 @@ struct _Py_freelists {
     struct _Py_freelist futureiters;
     struct _Py_freelist object_stack_chunks;
     struct _Py_freelist unicode_writers;
+    struct _Py_freelist pycfunctionobject;
+    struct _Py_freelist pycmethodobject;
     struct _Py_freelist pymethodobjects;
 };
 
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
new file mode 100644
index 00000000000000..6dc04135c7879e
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
@@ -0,0 +1 @@
+Improve performance of builtin methods by using a freelist.
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index ecec0f7205a11d..1f459dea44192c 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -4,6 +4,7 @@
 #include "Python.h"
 #include "pycore_call.h"          // _Py_CheckFunctionResult()
 #include "pycore_ceval.h"         // _Py_EnterRecursiveCallTstate()
+#include "pycore_freelist.h"
 #include "pycore_object.h"
 #include "pycore_pyerrors.h"
 #include "pycore_pystate.h"       // _PyThreadState_GET()
@@ -85,9 +86,12 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject 
*module, PyTypeObject *c
                             "flag but no class");
             return NULL;
         }
-        PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, 
&PyCMethod_Type);
+        PyCMethodObject *om = _Py_FREELIST_POP(PyCMethodObject, 
pycmethodobject);
         if (om == NULL) {
-            return NULL;
+            om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type);
+            if (om == NULL) {
+                return NULL;
+            }
         }
         om->mm_class = (PyTypeObject*)Py_NewRef(cls);
         op = (PyCFunctionObject *)om;
@@ -98,9 +102,12 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject 
*module, PyTypeObject *c
                             "but no METH_METHOD flag");
             return NULL;
         }
-        op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
+        op = _Py_FREELIST_POP(PyCFunctionObject, pycfunctionobject);
         if (op == NULL) {
-            return NULL;
+            op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
+            if (op == NULL) {
+                return NULL;
+            }
         }
     }
 
@@ -171,7 +178,14 @@ meth_dealloc(PyObject *self)
     Py_XDECREF(PyCFunction_GET_CLASS(m));
     Py_XDECREF(m->m_self);
     Py_XDECREF(m->m_module);
-    PyObject_GC_Del(m);
+    if (m->m_ml->ml_flags & METH_METHOD) {
+        assert(Py_IS_TYPE(self, &PyCMethod_Type));
+        _Py_FREELIST_FREE(pycmethodobject, m, PyObject_GC_Del);
+    }
+    else {
+        assert(Py_IS_TYPE(self, &PyCFunction_Type));
+        _Py_FREELIST_FREE(pycfunctionobject, m, PyObject_GC_Del);
+    }
     Py_TRASHCAN_END;
 }
 
diff --git a/Objects/object.c b/Objects/object.c
index 457ff17b980e75..42ac3a1c2baa7b 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -942,6 +942,8 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, 
int is_finalization)
     }
     clear_freelist(&freelists->unicode_writers, is_finalization, PyMem_Free);
     clear_freelist(&freelists->ints, is_finalization, free_object);
+    clear_freelist(&freelists->pycfunctionobject, is_finalization, 
PyObject_GC_Del);
+    clear_freelist(&freelists->pycmethodobject, is_finalization, 
PyObject_GC_Del);
     clear_freelist(&freelists->pymethodobjects, is_finalization, free_object);
 }
 

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to