| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d50c3f3 commit db067af
11 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -92,8 +92,8 @@ functions are thread-safe, the :term:`GIL <global interpreter lock>` does not | |||
| 92 | 92 | need to be held. | |
| 93 | 93 | ||
| 94 | 94 | The default raw memory block allocator uses the following functions: | |
| 95 | - :c:func:`malloc`, :c:func:`realloc` and :c:func:`free`; call ``malloc(1)`` when | ||
| 96 | - requesting zero bytes. | ||
| 95 | + :c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`; call | ||
| 96 | + ``malloc(1)`` (or ``calloc(1, 1)``) when requesting zero bytes. | ||
| 97 | 97 | ||
| 98 | 98 | .. versionadded:: 3.4 | |
| 99 | 99 | ||
@@ -106,6 +106,17 @@ requesting zero bytes. | |||
| 106 | 106 | been initialized in any way. | |
| 107 | 107 | ||
| 108 | 108 | ||
| 109 | + .. c:function:: void* PyMem_RawCalloc(size_t nelem, size_t elsize) | ||
| 110 | + | ||
| 111 | + Allocates *nelem* elements each whose size in bytes is *elsize* and returns | ||
| 112 | + a pointer of type :c:type:`void\*` to the allocated memory, or *NULL* if the | ||
| 113 | + request fails. The memory is initialized to zeros. Requesting zero elements | ||
| 114 | + or elements of size zero bytes returns a distinct non-*NULL* pointer if | ||
| 115 | + possible, as if ``PyMem_RawCalloc(1, 1)`` had been called instead. | ||
| 116 | + | ||
| 117 | + .. versionadded:: 3.5 | ||
| 118 | + | ||
| 119 | + | ||
| 109 | 120 | .. c:function:: void* PyMem_RawRealloc(void *p, size_t n) | |
| 110 | 121 | ||
| 111 | 122 | Resizes the memory block pointed to by *p* to *n* bytes. The contents will | |
@@ -136,8 +147,8 @@ behavior when requesting zero bytes, are available for allocating and releasing | |||
| 136 | 147 | memory from the Python heap. | |
| 137 | 148 | ||
| 138 | 149 | The default memory block allocator uses the following functions: | |
| 139 | - :c:func:`malloc`, :c:func:`realloc` and :c:func:`free`; call ``malloc(1)`` when | ||
| 140 | - requesting zero bytes. | ||
| 150 | + :c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`; call | ||
| 151 | + ``malloc(1)`` (or ``calloc(1, 1)``) when requesting zero bytes. | ||
| 141 | 152 | ||
| 142 | 153 | .. warning:: | |
| 143 | 154 | ||
@@ -152,6 +163,17 @@ requesting zero bytes. | |||
| 152 | 163 | been called instead. The memory will not have been initialized in any way. | |
| 153 | 164 | ||
| 154 | 165 | ||
| 166 | + .. c:function:: void* PyMem_Calloc(size_t nelem, size_t elsize) | ||
| 167 | + | ||
| 168 | + Allocates *nelem* elements each whose size in bytes is *elsize* and returns | ||
| 169 | + a pointer of type :c:type:`void\*` to the allocated memory, or *NULL* if the | ||
| 170 | + request fails. The memory is initialized to zeros. Requesting zero elements | ||
| 171 | + or elements of size zero bytes returns a distinct non-*NULL* pointer if | ||
| 172 | + possible, as if ``PyMem_Calloc(1, 1)`` had been called instead. | ||
| 173 | + | ||
| 174 | + .. versionadded:: 3.5 | ||
| 175 | + | ||
| 176 | + | ||
| 155 | 177 | .. c:function:: void* PyMem_Realloc(void *p, size_t n) | |
| 156 | 178 | ||
| 157 | 179 | Resizes the memory block pointed to by *p* to *n* bytes. The contents will be | |
@@ -222,11 +244,17 @@ Customize Memory Allocators | |||
| 222 | 244 | +----------------------------------------------------------+---------------------------------------+ | |
| 223 | 245 | | ``void* malloc(void *ctx, size_t size)`` | allocate a memory block | | |
| 224 | 246 | +----------------------------------------------------------+---------------------------------------+ | |
| 247 | + | ``void* calloc(void *ctx, size_t nelem, size_t elsize)`` | allocate a memory block initialized | | ||
| 248 | + | | with zeros | | ||
| 249 | + +----------------------------------------------------------+---------------------------------------+ | ||
| 225 | 250 | | ``void* realloc(void *ctx, void *ptr, size_t new_size)`` | allocate or resize a memory block | | |
| 226 | 251 | +----------------------------------------------------------+---------------------------------------+ | |
| 227 | 252 | | ``void free(void *ctx, void *ptr)`` | free a memory block | | |
| 228 | 253 | +----------------------------------------------------------+---------------------------------------+ | |
| 229 | 254 | ||
| 255 | + .. versionchanged:: 3.5 | ||
| 256 | + Add a new field ``calloc``. | ||
| 257 | + | ||
| 230 | 258 | .. c:type:: PyMemAllocatorDomain | |
| 231 | 259 | ||
| 232 | 260 | Enum used to identify an allocator domain. Domains: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -164,15 +164,23 @@ Optimizations | |||
| 164 | 164 | ||
| 165 | 165 | Major performance enhancements have been added: | |
| 166 | 166 | ||
| 167 | - * None yet. | ||
| 167 | + * Construction of ``bytes(int)`` and ``bytearray(int)`` (filled by zero bytes) | ||
| 168 | + is faster and use less memory (until the bytearray buffer is filled with | ||
| 169 | + data) for large objects. ``calloc()`` is used instead of ``malloc()`` to | ||
| 170 | + allocate memory for these objects. | ||
| 168 | 171 | ||
| 169 | 172 | ||
| 170 | 173 | Build and C API Changes | |
| 171 | 174 | ======================= | |
| 172 | 175 | ||
| 173 | 176 | Changes to Python's build process and to the C API include: | |
| 174 | 177 | ||
| 175 | - * None yet. | ||
| 178 | + * New ``calloc`` functions: | ||
| 179 | + | ||
| 180 | + * :c:func:`PyMem_RawCalloc` | ||
| 181 | + * :c:func:`PyMem_Calloc` | ||
| 182 | + * :c:func:`PyObject_Calloc` | ||
| 183 | + * :c:func:`_PyObject_GC_Calloc` | ||
| 176 | 184 | ||
| 177 | 185 | ||
| 178 | 186 | Deprecated | |
@@ -209,6 +217,9 @@ Porting to Python 3.5 | |||
| 209 | 217 | This section lists previously described changes and other bugfixes | |
| 210 | 218 | that may require changes to your code. | |
| 211 | 219 | ||
| 220 | + Changes in the Python API | ||
| 221 | + ------------------------- | ||
| 222 | + | ||
| 212 | 223 | * Before Python 3.5, a :class:`datetime.time` object was considered to be false | |
| 213 | 224 | if it represented midnight in UTC. This behavior was considered obscure and | |
| 214 | 225 | error-prone and has been removed in Python 3.5. See :issue:`13936` for full | |
@@ -217,3 +228,8 @@ that may require changes to your code. | |||
| 217 | 228 | * :meth:`ssl.SSLSocket.send()` now raises either :exc:`ssl.SSLWantReadError` | |
| 218 | 229 | or :exc:`ssl.SSLWantWriteError` on a non-blocking socket if the operation | |
| 219 | 230 | would block. Previously, it would return 0. See :issue:`20951`. | |
| 231 | + | ||
| 232 | + Changes in the C API | ||
| 233 | + -------------------- | ||
| 234 | + | ||
| 235 | + * The :c:type:`PyMemAllocator` structure has a new ``calloc`` field. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -95,6 +95,7 @@ PyObject_{New, NewVar, Del}. | |||
| 95 | 95 | the raw memory. | |
| 96 | 96 | */ | |
| 97 | 97 | PyAPI_FUNC(void *) PyObject_Malloc(size_t size); | |
| 98 | + PyAPI_FUNC(void *) PyObject_Calloc(size_t nelem, size_t elsize); | ||
| 98 | 99 | PyAPI_FUNC(void *) PyObject_Realloc(void *ptr, size_t new_size); | |
| 99 | 100 | PyAPI_FUNC(void) PyObject_Free(void *ptr); | |
| 100 | 101 | ||
@@ -321,7 +322,8 @@ extern PyGC_Head *_PyGC_generation0; | |||
| 321 | 322 | (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj))) | |
| 322 | 323 | #endif /* Py_LIMITED_API */ | |
| 323 | 324 | ||
| 324 | - PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t); | ||
| 325 | + PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t size); | ||
| 326 | + PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t size); | ||
| 325 | 327 | PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *); | |
| 326 | 328 | PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t); | |
| 327 | 329 | PyAPI_FUNC(void) PyObject_GC_Track(void *); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,6 +13,7 @@ extern "C" { | |||
| 13 | 13 | ||
| 14 | 14 | #ifndef Py_LIMITED_API | |
| 15 | 15 | PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size); | |
| 16 | + PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize); | ||
| 16 | 17 | PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size); | |
| 17 | 18 | PyAPI_FUNC(void) PyMem_RawFree(void *ptr); | |
| 18 | 19 | #endif | |
@@ -57,6 +58,7 @@ PyAPI_FUNC(void) PyMem_RawFree(void *ptr); | |||
| 57 | 58 | */ | |
| 58 | 59 | ||
| 59 | 60 | PyAPI_FUNC(void *) PyMem_Malloc(size_t size); | |
| 61 | + PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize); | ||
| 60 | 62 | PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size); | |
| 61 | 63 | PyAPI_FUNC(void) PyMem_Free(void *ptr); | |
| 62 | 64 | ||
@@ -132,6 +134,9 @@ typedef struct { | |||
| 132 | 134 | /* allocate a memory block */ | |
| 133 | 135 | void* (*malloc) (void *ctx, size_t size); | |
| 134 | 136 | ||
| 137 | + /* allocate a memory block initialized by zeros */ | ||
| 138 | + void* (*calloc) (void *ctx, size_t nelem, size_t elsize); | ||
| 139 | + | ||
| 135 | 140 | /* allocate or resize a memory block */ | |
| 136 | 141 | void* (*realloc) (void *ctx, void *ptr, size_t new_size); | |
| 137 | 142 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,12 @@ Release date: TBA | |||
| 10 | 10 | Core and Builtins | |
| 11 | 11 | ----------------- | |
| 12 | 12 | ||
| 13 | + - Issue #21233: Add new C functions: PyMem_RawCalloc(), PyMem_Calloc(), | ||
| 14 | + PyObject_Calloc(), _PyObject_GC_Calloc(). bytes(int) and bytearray(int) | ||
| 15 | + are now using ``calloc()`` instead of ``malloc()`` for large objects which | ||
| 16 | + is faster and use less memory (until the bytearray buffer is filled with | ||
| 17 | + data). | ||
| 18 | + | ||
| 13 | 19 | - Issue #21377: PyBytes_Concat() now tries to concatenate in-place when the | |
| 14 | 20 | first argument has a reference count of 1. Patch by Nikolaus Rath. | |
| 15 | 21 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2710,27 +2710,57 @@ test_pymem_alloc0(PyObject *self) | |||
| 2710 | 2710 | { | |
| 2711 | 2711 | void *ptr; | |
| 2712 | 2712 | ||
| 2713 | + ptr = PyMem_RawMalloc(0); | ||
| 2714 | + if (ptr == NULL) { | ||
| 2715 | + PyErr_SetString(PyExc_RuntimeError, "PyMem_RawMalloc(0) returns NULL"); | ||
| 2716 | + return NULL; | ||
| 2717 | + } | ||
| 2718 | + PyMem_RawFree(ptr); | ||
| 2719 | + | ||
| 2720 | + ptr = PyMem_RawCalloc(0, 0); | ||
| 2721 | + if (ptr == NULL) { | ||
| 2722 | + PyErr_SetString(PyExc_RuntimeError, "PyMem_RawCalloc(0, 0) returns NULL"); | ||
| 2723 | + return NULL; | ||
| 2724 | + } | ||
| 2725 | + PyMem_RawFree(ptr); | ||
| 2726 | + | ||
| 2713 | 2727 | ptr = PyMem_Malloc(0); | |
| 2714 | 2728 | if (ptr == NULL) { | |
| 2715 | 2729 | PyErr_SetString(PyExc_RuntimeError, "PyMem_Malloc(0) returns NULL"); | |
| 2716 | 2730 | return NULL; | |
| 2717 | 2731 | } | |
| 2718 | 2732 | PyMem_Free(ptr); | |
| 2719 | 2733 | ||
| 2734 | + ptr = PyMem_Calloc(0, 0); | ||
| 2735 | + if (ptr == NULL) { | ||
| 2736 | + PyErr_SetString(PyExc_RuntimeError, "PyMem_Calloc(0, 0) returns NULL"); | ||
| 2737 | + return NULL; | ||
| 2738 | + } | ||
| 2739 | + PyMem_Free(ptr); | ||
| 2740 | + | ||
| 2720 | 2741 | ptr = PyObject_Malloc(0); | |
| 2721 | 2742 | if (ptr == NULL) { | |
| 2722 | 2743 | PyErr_SetString(PyExc_RuntimeError, "PyObject_Malloc(0) returns NULL"); | |
| 2723 | 2744 | return NULL; | |
| 2724 | 2745 | } | |
| 2725 | 2746 | PyObject_Free(ptr); | |
| 2726 | 2747 | ||
| 2748 | + ptr = PyObject_Calloc(0, 0); | ||
| 2749 | + if (ptr == NULL) { | ||
| 2750 | + PyErr_SetString(PyExc_RuntimeError, "PyObject_Calloc(0, 0) returns NULL"); | ||
| 2751 | + return NULL; | ||
| 2752 | + } | ||
| 2753 | + PyObject_Free(ptr); | ||
| 2754 | + | ||
| 2727 | 2755 | Py_RETURN_NONE; | |
| 2728 | 2756 | } | |
| 2729 | 2757 | ||
| 2730 | 2758 | typedef struct { | |
| 2731 | 2759 | PyMemAllocator alloc; | |
| 2732 | 2760 | ||
| 2733 | 2761 | size_t malloc_size; | |
| 2762 | + size_t calloc_nelem; | ||
| 2763 | + size_t calloc_elsize; | ||
| 2734 | 2764 | void *realloc_ptr; | |
| 2735 | 2765 | size_t realloc_new_size; | |
| 2736 | 2766 | void *free_ptr; | |
@@ -2743,6 +2773,14 @@ static void* hook_malloc (void* ctx, size_t size) | |||
| 2743 | 2773 | return hook->alloc.malloc(hook->alloc.ctx, size); | |
| 2744 | 2774 | } | |
| 2745 | 2775 | ||
| 2776 | + static void* hook_calloc (void* ctx, size_t nelem, size_t elsize) | ||
| 2777 | + { | ||
| 2778 | + alloc_hook_t *hook = (alloc_hook_t *)ctx; | ||
| 2779 | + hook->calloc_nelem = nelem; | ||
| 2780 | + hook->calloc_elsize = elsize; | ||
| 2781 | + return hook->alloc.calloc(hook->alloc.ctx, nelem, elsize); | ||
| 2782 | + } | ||
| 2783 | + | ||
| 2746 | 2784 | static void* hook_realloc (void* ctx, void* ptr, size_t new_size) | |
| 2747 | 2785 | { | |
| 2748 | 2786 | alloc_hook_t *hook = (alloc_hook_t *)ctx; | |
@@ -2765,16 +2803,14 @@ test_setallocators(PyMemAllocatorDomain domain) | |||
| 2765 | 2803 | const char *error_msg; | |
| 2766 | 2804 | alloc_hook_t hook; | |
| 2767 | 2805 | PyMemAllocator alloc; | |
| 2768 | - size_t size, size2; | ||
| 2806 | + size_t size, size2, nelem, elsize; | ||
| 2769 | 2807 | void *ptr, *ptr2; | |
| 2770 | 2808 | ||
| 2771 | - hook.malloc_size = 0; | ||
| 2772 | - hook.realloc_ptr = NULL; | ||
| 2773 | - hook.realloc_new_size = 0; | ||
| 2774 | - hook.free_ptr = NULL; | ||
| 2809 | + memset(&hook, 0, sizeof(hook)); | ||
| 2775 | 2810 | ||
| 2776 | 2811 | alloc.ctx = &hook; | |
| 2777 | 2812 | alloc.malloc = &hook_malloc; | |
| 2813 | + alloc.calloc = &hook_calloc; | ||
| 2778 | 2814 | alloc.realloc = &hook_realloc; | |
| 2779 | 2815 | alloc.free = &hook_free; | |
| 2780 | 2816 | PyMem_GetAllocator(domain, &hook.alloc); | |
@@ -2831,6 +2867,33 @@ test_setallocators(PyMemAllocatorDomain domain) | |||
| 2831 | 2867 | goto fail; | |
| 2832 | 2868 | } | |
| 2833 | 2869 | ||
| 2870 | + nelem = 2; | ||
| 2871 | + elsize = 5; | ||
| 2872 | + switch(domain) | ||
| 2873 | + { | ||
| 2874 | + case PYMEM_DOMAIN_RAW: ptr = PyMem_RawCalloc(nelem, elsize); break; | ||
| 2875 | + case PYMEM_DOMAIN_MEM: ptr = PyMem_Calloc(nelem, elsize); break; | ||
| 2876 | + case PYMEM_DOMAIN_OBJ: ptr = PyObject_Calloc(nelem, elsize); break; | ||
| 2877 | + default: ptr = NULL; break; | ||
| 2878 | + } | ||
| 2879 | + | ||
| 2880 | + if (ptr == NULL) { | ||
| 2881 | + error_msg = "calloc failed"; | ||
| 2882 | + goto fail; | ||
| 2883 | + } | ||
| 2884 | + | ||
| 2885 | + if (hook.calloc_nelem != nelem || hook.calloc_elsize != elsize) { | ||
| 2886 | + error_msg = "calloc invalid nelem or elsize"; | ||
| 2887 | + goto fail; | ||
| 2888 | + } | ||
| 2889 | + | ||
| 2890 | + switch(domain) | ||
| 2891 | + { | ||
| 2892 | + case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break; | ||
| 2893 | + case PYMEM_DOMAIN_MEM: PyMem_Free(ptr); break; | ||
| 2894 | + case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break; | ||
| 2895 | + } | ||
| 2896 | + | ||
| 2834 | 2897 | Py_INCREF(Py_None); | |
| 2835 | 2898 | res = Py_None; | |
| 2836 | 2899 | goto finally; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments