]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-126868: Add freelist for compact ints to `_PyLong_New` (#128181)
authorPieter Eendebak <pieter.eendebak@gmail.com>
Thu, 26 Dec 2024 15:17:22 +0000 (16:17 +0100)
committerGitHub <noreply@github.com>
Thu, 26 Dec 2024 15:17:22 +0000 (15:17 +0000)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Misc/NEWS.d/next/Core_and_Builtins/2024-12-22-15-47-44.gh-issue-126868.RpjKez.rst [new file with mode: 0644]
Objects/longobject.c

diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-22-15-47-44.gh-issue-126868.RpjKez.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-22-15-47-44.gh-issue-126868.RpjKez.rst
new file mode 100644 (file)
index 0000000..ede383d
--- /dev/null
@@ -0,0 +1 @@
+Increase usage of freelist for :class:`int` allocation.
index bd7ff68d0899c6ad1a489633b0ddf64c7b3421b1..d449a01cedf8863476c8ac7562ef3c3245c06d68 100644 (file)
@@ -156,7 +156,7 @@ PyLongObject *
 _PyLong_New(Py_ssize_t size)
 {
     assert(size >= 0);
-    PyLongObject *result;
+    PyLongObject *result = NULL;
     if (size > (Py_ssize_t)MAX_LONG_DIGITS) {
         PyErr_SetString(PyExc_OverflowError,
                         "too many digits in integer");
@@ -165,19 +165,25 @@ _PyLong_New(Py_ssize_t size)
     /* Fast operations for single digit integers (including zero)
      * assume that there is always at least one digit present. */
     Py_ssize_t ndigits = size ? size : 1;
-    /* Number of bytes needed is: offsetof(PyLongObject, ob_digit) +
-       sizeof(digit)*size.  Previous incarnations of this code used
-       sizeof() instead of the offsetof, but this risks being
-       incorrect in the presence of padding between the header
-       and the digits. */
-    result = PyObject_Malloc(offsetof(PyLongObject, long_value.ob_digit) +
-                             ndigits*sizeof(digit));
-    if (!result) {
-        PyErr_NoMemory();
-        return NULL;
+
+    if (ndigits == 1) {
+        result = (PyLongObject *)_Py_FREELIST_POP(PyLongObject, ints);
+    }
+    if (result == NULL) {
+        /* Number of bytes needed is: offsetof(PyLongObject, ob_digit) +
+        sizeof(digit)*size.  Previous incarnations of this code used
+        sizeof() instead of the offsetof, but this risks being
+        incorrect in the presence of padding between the header
+        and the digits. */
+        result = PyObject_Malloc(offsetof(PyLongObject, long_value.ob_digit) +
+                                ndigits*sizeof(digit));
+        if (!result) {
+            PyErr_NoMemory();
+            return NULL;
+        }
+        _PyObject_Init((PyObject*)result, &PyLong_Type);
     }
     _PyLong_SetSignAndDigitCount(result, size != 0, size);
-    _PyObject_Init((PyObject*)result, &PyLong_Type);
     /* The digit has to be initialized explicitly to avoid
      * use-of-uninitialized-value. */
     result->long_value.ob_digit[0] = 0;