https://github.com/python/cpython/commit/ff39e3ff7bebc9d700d89c5cd22145db2c879cf2
commit: ff39e3ff7bebc9d700d89c5cd22145db2c879cf2
branch: main
author: Pieter Eendebak <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-01-12T18:31:49+05:30
summary:

gh-126703: Add freelist for `PyMethodObject` (#128594)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-48-56.gh-issue-126703.0ISs-7.rst
M Include/internal/pycore_freelist_state.h
M Objects/classobject.c
M Objects/object.c

diff --git a/Include/internal/pycore_freelist_state.h 
b/Include/internal/pycore_freelist_state.h
index a1a94c1f2dc880..2ccd1ac055b747 100644
--- a/Include/internal/pycore_freelist_state.h
+++ b/Include/internal/pycore_freelist_state.h
@@ -22,6 +22,7 @@ extern "C" {
 #  define Py_futureiters_MAXFREELIST 255
 #  define Py_object_stack_chunks_MAXFREELIST 4
 #  define Py_unicode_writers_MAXFREELIST 1
+#  define Py_pymethodobjects_MAXFREELIST 20
 
 // A generic freelist of either PyObjects or other data structures.
 struct _Py_freelist {
@@ -48,6 +49,7 @@ struct _Py_freelists {
     struct _Py_freelist futureiters;
     struct _Py_freelist object_stack_chunks;
     struct _Py_freelist unicode_writers;
+    struct _Py_freelist pymethodobjects;
 };
 
 #ifdef __cplusplus
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-48-56.gh-issue-126703.0ISs-7.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-48-56.gh-issue-126703.0ISs-7.rst
new file mode 100644
index 00000000000000..ecb8eddb13c649
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-07-19-48-56.gh-issue-126703.0ISs-7.rst
@@ -0,0 +1 @@
+Improve performance of class methods by using a freelist.
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 775894ad5a7166..58e1d17977322e 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -3,6 +3,7 @@
 #include "Python.h"
 #include "pycore_call.h"          // _PyObject_VectorcallTstate()
 #include "pycore_ceval.h"         // _PyEval_GetBuiltin()
+#include "pycore_freelist.h"
 #include "pycore_object.h"
 #include "pycore_pyerrors.h"
 #include "pycore_pystate.h"       // _PyThreadState_GET()
@@ -112,9 +113,12 @@ PyMethod_New(PyObject *func, PyObject *self)
         PyErr_BadInternalCall();
         return NULL;
     }
-    PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
+    PyMethodObject *im = _Py_FREELIST_POP(PyMethodObject, pymethodobjects);
     if (im == NULL) {
-        return NULL;
+        im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
+        if (im == NULL) {
+            return NULL;
+        }
     }
     im->im_weakreflist = NULL;
     im->im_func = Py_NewRef(func);
@@ -245,7 +249,8 @@ method_dealloc(PyObject *self)
         PyObject_ClearWeakRefs((PyObject *)im);
     Py_DECREF(im->im_func);
     Py_XDECREF(im->im_self);
-    PyObject_GC_Del(im);
+    assert(Py_IS_TYPE(self, &PyMethod_Type));
+    _Py_FREELIST_FREE(pymethodobjects, (PyObject *)im, PyObject_GC_Del);
 }
 
 static PyObject *
diff --git a/Objects/object.c b/Objects/object.c
index 4c30257ca26938..9befd92e3231c8 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -937,6 +937,7 @@ _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->pymethodobjects, is_finalization, free_object);
 }
 
 /*

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to