Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
gh-144319: Add huge pages support for pymalloc
  • Loading branch information
pablogsal committed Jan 29, 2026
commit 16ecc7e53bad60f9f6eeadbe7dac4104c3d1afe0
6 changes: 5 additions & 1 deletion Doc/c-api/memory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,11 @@ The pymalloc allocator
Python has a *pymalloc* allocator optimized for small objects (smaller or equal
to 512 bytes) with a short lifetime. It uses memory mappings called "arenas"
with a fixed size of either 256 KiB on 32-bit platforms or 1 MiB on 64-bit
platforms. It falls back to :c:func:`PyMem_RawMalloc` and
platforms. When Python is configured with :option:`--with-pymalloc-hugepages`,
the arena size on 64-bit platforms is increased to 2 MiB to match the huge page
size, and arena allocation will attempt to use huge pages (``MAP_HUGETLB`` on
Linux, ``MEM_LARGE_PAGES`` on Windows) with automatic fallback to regular pages.
It falls back to :c:func:`PyMem_RawMalloc` and
:c:func:`PyMem_RawRealloc` for allocations larger than 512 bytes.

*pymalloc* is the :ref:`default allocator <default-memory-allocators>` of the
Expand Down
12 changes: 12 additions & 0 deletions Doc/using/configure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,18 @@ also be used to improve performance.

See also :envvar:`PYTHONMALLOC` environment variable.

.. option:: --with-pymalloc-hugepages

Enable huge page support for :ref:`pymalloc <pymalloc>` arenas (disabled by
default). When enabled, the arena size on 64-bit platforms is increased to
2 MiB and arena allocation uses ``MAP_HUGETLB`` (Linux) or
``MEM_LARGE_PAGES`` (Windows) with automatic fallback to regular pages.

The configure script checks that the platform supports ``MAP_HUGETLB``
and emits a warning if it is not available.

.. versionadded:: 3.15

.. option:: --without-doc-strings

Disable static documentation strings to reduce the memory footprint (enabled
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,11 @@ Build changes
modules that are missing or packaged separately.
(Contributed by Stan Ulbrych and Petr Viktorin in :gh:`139707`.)

* The new configure option :option:`--with-pymalloc-hugepages` enables huge
page support for :ref:`pymalloc <pymalloc>` arenas. When enabled, arena size
increases to 2 MiB and allocation uses ``MAP_HUGETLB`` (Linux) or
``MEM_LARGE_PAGES`` (Windows) with automatic fallback to regular pages.

* Annotating anonymous mmap usage is now supported if Linux kernel supports
:manpage:`PR_SET_VMA_ANON_NAME <PR_SET_VMA(2const)>` (Linux 5.17 or newer).
Annotations are visible in ``/proc/<pid>/maps`` if the kernel supports the feature
Expand Down
22 changes: 19 additions & 3 deletions Include/internal/pycore_obmalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,11 @@ typedef unsigned int pymem_uint; /* assuming >= 16 bits */
* mappings to reduce heap fragmentation.
*/
#ifdef USE_LARGE_ARENAS
#define ARENA_BITS 20 /* 1 MiB */
# ifdef PYMALLOC_USE_HUGEPAGES
# define ARENA_BITS 21 /* 2 MiB */
# else
# define ARENA_BITS 20 /* 1 MiB */
# endif
#else
#define ARENA_BITS 18 /* 256 KiB */
#endif
Expand Down Expand Up @@ -469,7 +473,7 @@ nfp free pools in usable_arenas.
*/

/* How many arena_objects do we initially allocate?
* 16 = can allocate 16 arenas = 16 * ARENA_SIZE = 4MB before growing the
* 16 = can allocate 16 arenas = 16 * ARENA_SIZE before growing the
* `arenas` vector.
*/
#define INITIAL_ARENA_OBJECTS 16
Expand Down Expand Up @@ -512,14 +516,26 @@ struct _obmalloc_mgmt {

memory address bit allocation for keys

64-bit pointers, IGNORE_BITS=0 and 2^20 arena size:
ARENA_BITS is configurable: 20 (1 MiB) by default on 64-bit, or
21 (2 MiB) when PYMALLOC_USE_HUGEPAGES is enabled. All bit widths
below are derived from ARENA_BITS automatically.

64-bit pointers, IGNORE_BITS=0 and 2^20 arena size (default):
15 -> MAP_TOP_BITS
15 -> MAP_MID_BITS
14 -> MAP_BOT_BITS
20 -> ideal aligned arena
----
64

64-bit pointers, IGNORE_BITS=0 and 2^21 arena size (hugepages):
15 -> MAP_TOP_BITS
15 -> MAP_MID_BITS
13 -> MAP_BOT_BITS
21 -> ideal aligned arena
----
64

64-bit pointers, IGNORE_BITS=16, and 2^20 arena size:
16 -> IGNORE_BITS
10 -> MAP_TOP_BITS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add huge pages support for the pymalloc allocator. Patch by Pablo Galindo
20 changes: 20 additions & 0 deletions Objects/obmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,10 +496,30 @@ void *
_PyMem_ArenaAlloc(void *Py_UNUSED(ctx), size_t size)
{
#ifdef MS_WINDOWS
# ifdef PYMALLOC_USE_HUGEPAGES
void *ptr = VirtualAlloc(NULL, size,
MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
PAGE_READWRITE);
if (ptr != NULL)
return ptr;
/* Fall back to regular pages */
# endif
return VirtualAlloc(NULL, size,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#elif defined(ARENAS_USE_MMAP)
void *ptr;
# ifdef PYMALLOC_USE_HUGEPAGES
# ifdef MAP_HUGETLB
ptr = mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB, -1, 0);
if (ptr != MAP_FAILED) {
assert(ptr != NULL);
(void)_PyAnnotateMemoryMap(ptr, size, "cpython:pymalloc:hugepage");
return ptr;
}
/* Fall back to regular pages */
# endif
# endif
ptr = mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (ptr == MAP_FAILED)
Expand Down
47 changes: 47 additions & 0 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5061,6 +5061,29 @@ then
fi
AC_MSG_RESULT([$with_pymalloc])

AC_MSG_CHECKING([for --with-pymalloc-hugepages])
AC_ARG_WITH(
[pymalloc-hugepages],
[AS_HELP_STRING([--with-pymalloc-hugepages],
[enable huge page support for pymalloc arenas (default is no)])])
if test "$with_pymalloc_hugepages" = "yes"
then
dnl configure only runs on Unix-like systems; Windows uses MEM_LARGE_PAGES
dnl via VirtualAlloc but does not use configure. Only check MAP_HUGETLB here.
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/mman.h>
]], [[
int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB;
(void)flags;
]])],
[AC_DEFINE([PYMALLOC_USE_HUGEPAGES], [1],
[Define to use huge pages for pymalloc arenas])],
[AC_MSG_WARN([--with-pymalloc-hugepages requested but MAP_HUGETLB not found])
with_pymalloc_hugepages=no])
fi
AC_MSG_RESULT([${with_pymalloc_hugepages:-no}])

# Check for --with-c-locale-coercion
AC_MSG_CHECKING([for --with-c-locale-coercion])
AC_ARG_WITH(
Expand Down
3 changes: 3 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,9 @@
/* Define as the preferred size in bits of long digits */
#undef PYLONG_BITS_IN_DIGIT

/* Define to use huge pages for pymalloc arenas */
#undef PYMALLOC_USE_HUGEPAGES

/* enabled builtin hash modules */
#undef PY_BUILTIN_HASHLIB_HASHES

Expand Down
Loading