Skip to content

Commit aff7a2e

Browse files
authored
gh-159111: Update vendored mimalloc to v2.5.2 (gh-159112)
* Update vendored mimalloc to v2.5.2 Upgrade mimalloc from v2.1.2 to v2.5.2 as-is from upstream. v2.1.2: https://github.com/microsoft/mimalloc/releases/tag/v2.1.2 v2.5.2: https://github.com/microsoft/mimalloc/releases/tag/v2.5.2 * Re-apply CPython-specific changes to mimalloc v2.5.2 Most of the previous downstream changes were upstreamed in mimalloc v2.1.3 - v2.1.7 (heap tags, _mi_heap_init/_mi_tld_init, MI_PRIM_THREAD_ID, sub-processes, heap walk optimizations, platform fixes) and are dropped. Remaining CPython-specific changes, all marked with a "CPython" comment: - QSBR delayed page freeing for free-threaded builds (gh-115103, gh-145615): mi_page_t/mi_heap_t fields and _PyMem_mi_* hooks in page.c, heap.c and segment.c. - debug_offset: preserve the first bytes of a PyObject (ob_tid, refcount fields) when filling freed or uninitialized memory in debug builds (gh-115491). - Atomic mi_block_t.next loads/stores to avoid TSAN reports (gh-129748). - Relax the owning thread assertion in _mi_free_delayed_block for free-threaded builds, since the GC traverses heaps of other threads. - Call _mi_heap_delayed_free_partial() in mi_heap_visit_blocks() (gh-112532). - Only count reclaimed pages up to MI_MEDIUM_OBJ_SIZE_MAX as a "right page" in mi_segment_reclaim (gh-115103). - Rename the weak _ZSt15get_new_handlerv symbol and disable the mi_is_in_heap_region debug warning. - Zero-initialize _mi_page_empty instead of a positional initializer. * Update the free-threaded build to mimalloc v2.5.2 changes mimalloc v2.1.4 replaced the list of abandoned segments with per-arena bitmaps and introduced sub-processes (mi_subproc_t) to keep abandoned segments of separate interpreters apart. Use them instead of the CPython-specific mi_abandoned_pool_t: - Each interpreter owns a mi_subproc_t created in init_interpreter(). - tstate_mimalloc_bind() sets tld->segments.subproc and uses the upstream _mi_heap_init() signature. - The GC and sys.getallocatedblocks() visit abandoned segments with _PyMem_mi_visit_abandoned_blocks(), the upstream cursor API without the mi_option_visit_abandoned requirement, while STW. * Update NEWS.d * fix MSAN * fix TSAN * fix test_cext * Disable THP * Address code review * Address code review * Address code review * nit * Address code review * Address code review
1 parent ab5187c commit aff7a2e

45 files changed

Lines changed: 7566 additions & 3442 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Doc/license.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,7 @@ mimalloc
10341034

10351035
MIT License::
10361036

1037-
Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen
1037+
Copyright (c) 2018-2025 Microsoft Corporation, Daan Leijen
10381038

10391039
Permission is hereby granted, free of charge, to any person obtaining a copy
10401040
of this software and associated documentation files (the "Software"), to deal

‎Doc/whatsnew/3.16.rst‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,11 @@ Build changes
12951295

12961296
(Contributed by Stan Ulbrych, Florian Mayer and AnnaAr321 in :gh:`156049`.)
12971297

1298+
* Update the bundled `mimalloc library`_ from version 2.1.2 to 2.5.2.
1299+
(Contributed by Donghee Na in :gh:`159111`.)
1300+
1301+
.. _mimalloc library: https://github.com/microsoft/mimalloc/
1302+
12981303

12991304
C API changes
13001305
=============
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* ----------------------------------------------------------------------------
2+
Copyright (c) 2018-2025, Microsoft Research, Daan Leijen
3+
This is free software; you can redistribute it and/or modify it under the
4+
terms of the MIT license. A copy of the license can be found in the file
5+
"LICENSE" at the root of this distribution.
6+
-----------------------------------------------------------------------------*/
7+
#pragma once
8+
#ifndef MIMALLOC_STATS_H
9+
#define MIMALLOC_STATS_H
10+
11+
#include "mimalloc.h"
12+
#include <stdint.h>
13+
14+
#define MI_STAT_VERSION 4 // increased on every backward incompatible change
15+
16+
// count allocation over time
17+
typedef struct mi_stat_count_s {
18+
int64_t total; // total allocated
19+
int64_t peak; // peak allocation
20+
int64_t current; // current allocation
21+
} mi_stat_count_t;
22+
23+
// counters only increase
24+
typedef struct mi_stat_counter_s {
25+
int64_t total; // total count
26+
} mi_stat_counter_t;
27+
28+
#define MI_STAT_FIELDS() \
29+
MI_STAT_COUNT(pages) /* count of mimalloc pages */ \
30+
MI_STAT_COUNT(reserved) /* reserved memory bytes */ \
31+
MI_STAT_COUNT(committed) /* committed bytes */ \
32+
MI_STAT_COUNTER(reset) /* reset bytes */ \
33+
MI_STAT_COUNTER(purged) /* purged bytes */ \
34+
MI_STAT_COUNT(page_committed) /* committed memory inside pages */ \
35+
MI_STAT_COUNT(pages_abandoned) /* abandoned pages count */ \
36+
MI_STAT_COUNT(threads) /* number of threads */ \
37+
MI_STAT_COUNT(malloc_normal) /* allocated bytes <= MI_LARGE_OBJ_SIZE_MAX */ \
38+
MI_STAT_COUNT(malloc_huge) /* allocated bytes in huge pages */ \
39+
MI_STAT_COUNT(malloc_requested) /* malloc requested bytes */ \
40+
\
41+
MI_STAT_COUNTER(mmap_calls) \
42+
MI_STAT_COUNTER(commit_calls) \
43+
MI_STAT_COUNTER(reset_calls) \
44+
MI_STAT_COUNTER(purge_calls) \
45+
MI_STAT_COUNTER(arena_count) /* number of memory arena's */ \
46+
MI_STAT_COUNTER(malloc_normal_count) /* number of blocks <= MI_LARGE_OBJ_SIZE_MAX */ \
47+
MI_STAT_COUNTER(malloc_huge_count) /* number of huge bloks */ \
48+
MI_STAT_COUNTER(malloc_guarded_count) /* number of allocations with guard pages */ \
49+
\
50+
/* internal statistics */ \
51+
MI_STAT_COUNTER(arena_rollback_count) \
52+
MI_STAT_COUNTER(arena_purges) \
53+
MI_STAT_COUNTER(pages_extended) /* number of page extensions */ \
54+
MI_STAT_COUNTER(pages_retire) /* number of pages that are retired */ \
55+
MI_STAT_COUNTER(page_searches) /* total pages searched for a fresh page */ \
56+
MI_STAT_COUNTER(page_searches_count) /* searched count for a fresh page */ \
57+
/* only on v1 and v2 */ \
58+
MI_STAT_COUNT(segments) \
59+
MI_STAT_COUNT(segments_abandoned) \
60+
MI_STAT_COUNT(segments_cache) \
61+
MI_STAT_COUNT(_segments_reserved) \
62+
/* only on v3 */ \
63+
MI_STAT_COUNTER(pages_reclaim_on_alloc) \
64+
MI_STAT_COUNTER(pages_reclaim_on_free) \
65+
MI_STAT_COUNTER(pages_reabandon_full) \
66+
MI_STAT_COUNTER(pages_unabandon_busy_wait) \
67+
68+
69+
// Define the statistics structure
70+
#define MI_BIN_HUGE (73U) // see types.h
71+
#define MI_STAT_COUNT(stat) mi_stat_count_t stat;
72+
#define MI_STAT_COUNTER(stat) mi_stat_counter_t stat;
73+
74+
typedef struct mi_stats_s
75+
{
76+
size_t size; // size of the mi_stats_t structure
77+
size_t version;
78+
79+
MI_STAT_FIELDS()
80+
81+
// future extension
82+
mi_stat_count_t _stat_reserved[4];
83+
mi_stat_counter_t _stat_counter_reserved[4];
84+
85+
// size segregated statistics
86+
mi_stat_count_t malloc_bins[MI_BIN_HUGE+1]; // allocation per size bin
87+
mi_stat_count_t page_bins[MI_BIN_HUGE+1]; // pages allocated per size bin
88+
} mi_stats_t;
89+
90+
#undef MI_STAT_COUNT
91+
#undef MI_STAT_COUNTER
92+
93+
// helper
94+
#define mi_stats_t_decl(name) mi_stats_t name = { 0 }; name.size = sizeof(mi_stats_t); name.version = MI_STAT_VERSION;
95+
96+
// Exported definitions
97+
#ifdef __cplusplus
98+
extern "C" {
99+
#endif
100+
101+
mi_decl_export bool mi_stats_get( mi_stats_t* stats ) mi_attr_noexcept;
102+
mi_decl_export char* mi_stats_get_json( size_t buf_size, char* buf ) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL
103+
104+
#ifdef __cplusplus
105+
}
106+
#endif
107+
108+
#endif // MIMALLOC_STATS_H

0 commit comments

Comments
 (0)