mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-04 22:49:32 +03:00
make reclaim tries a percentage of the abandoned count
This commit is contained in:
parent
cf8f73098e
commit
c4f1f2e079
4 changed files with 16 additions and 5 deletions
|
@ -126,6 +126,7 @@ void _mi_arena_unsafe_destroy_all(mi_stats_t* stats);
|
||||||
|
|
||||||
bool _mi_arena_segment_clear_abandoned(mi_memid_t memid);
|
bool _mi_arena_segment_clear_abandoned(mi_memid_t memid);
|
||||||
void _mi_arena_segment_mark_abandoned(mi_memid_t memid);
|
void _mi_arena_segment_mark_abandoned(mi_memid_t memid);
|
||||||
|
size_t _mi_arena_segment_abandoned_count(void);
|
||||||
|
|
||||||
typedef struct mi_arena_field_cursor_s { // abstract
|
typedef struct mi_arena_field_cursor_s { // abstract
|
||||||
mi_arena_id_t start;
|
mi_arena_id_t start;
|
||||||
|
|
10
src/arena.c
10
src/arena.c
|
@ -733,14 +733,18 @@ bool _mi_arena_contains(const void* p) {
|
||||||
This is used to atomically abandon/reclaim segments
|
This is used to atomically abandon/reclaim segments
|
||||||
(and crosses the arena API but it is convenient to have here).
|
(and crosses the arena API but it is convenient to have here).
|
||||||
Abandoned segments still have live blocks; they get reclaimed
|
Abandoned segments still have live blocks; they get reclaimed
|
||||||
when a thread frees in it, or when a thread needs a fresh
|
when a thread frees a block in it, or when a thread needs a fresh
|
||||||
segment; these threads scan the abandoned segments through
|
segment; these threads scan the abandoned segments through
|
||||||
the arena bitmaps.
|
the arena bitmaps.
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
// Maintain these for debug purposes
|
// Maintain a count of all abandoned segments
|
||||||
static mi_decl_cache_align _Atomic(size_t)abandoned_count;
|
static mi_decl_cache_align _Atomic(size_t)abandoned_count;
|
||||||
|
|
||||||
|
size_t _mi_arena_segment_abandoned_count(void) {
|
||||||
|
return mi_atomic_load_relaxed(&abandoned_count);
|
||||||
|
}
|
||||||
|
|
||||||
// reclaim a specific abandoned segment; `true` on success.
|
// reclaim a specific abandoned segment; `true` on success.
|
||||||
bool _mi_arena_segment_clear_abandoned(mi_memid_t memid )
|
bool _mi_arena_segment_clear_abandoned(mi_memid_t memid )
|
||||||
{
|
{
|
||||||
|
@ -885,7 +889,7 @@ static bool mi_manage_os_memory_ex2(void* start, size_t size, bool is_large, int
|
||||||
// consequetive bitmaps
|
// consequetive bitmaps
|
||||||
arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap
|
arena->blocks_dirty = &arena->blocks_inuse[fields]; // just after inuse bitmap
|
||||||
arena->blocks_abandoned = &arena->blocks_inuse[2 * fields]; // just after dirty bitmap
|
arena->blocks_abandoned = &arena->blocks_inuse[2 * fields]; // just after dirty bitmap
|
||||||
arena->blocks_committed = (arena->memid.is_pinned ? NULL : &arena->blocks_inuse[3*fields]); // just after abandonde bitmap
|
arena->blocks_committed = (arena->memid.is_pinned ? NULL : &arena->blocks_inuse[3*fields]); // just after abandoned bitmap
|
||||||
arena->blocks_purge = (arena->memid.is_pinned ? NULL : &arena->blocks_inuse[4*fields]); // just after committed bitmap
|
arena->blocks_purge = (arena->memid.is_pinned ? NULL : &arena->blocks_inuse[4*fields]); // just after committed bitmap
|
||||||
// initialize committed bitmap?
|
// initialize committed bitmap?
|
||||||
if (arena->blocks_committed != NULL && arena->memid.initially_committed) {
|
if (arena->blocks_committed != NULL && arena->memid.initially_committed) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ static mi_option_desc_t options[_mi_option_last] =
|
||||||
{ 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose
|
{ 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose
|
||||||
{ 16, UNINIT, MI_OPTION(max_errors) }, // maximum errors that are output
|
{ 16, UNINIT, MI_OPTION(max_errors) }, // maximum errors that are output
|
||||||
{ 16, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output
|
{ 16, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output
|
||||||
{ 16, UNINIT, MI_OPTION(max_segment_reclaim)}, // max. number of segment reclaims from the abandoned segments per try.
|
{ 10, UNINIT, MI_OPTION(max_segment_reclaim)}, // max. percentage of the abandoned segments per try.
|
||||||
{ 0, UNINIT, MI_OPTION(destroy_on_exit)}, // release all OS memory on process exit; careful with dangling pointer or after-exit frees!
|
{ 0, UNINIT, MI_OPTION(destroy_on_exit)}, // release all OS memory on process exit; careful with dangling pointer or after-exit frees!
|
||||||
#if (MI_INTPTR_SIZE>4)
|
#if (MI_INTPTR_SIZE>4)
|
||||||
{ 1024L * 1024L, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time
|
{ 1024L * 1024L, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time
|
||||||
|
|
|
@ -921,7 +921,13 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size,
|
||||||
*reclaimed = false;
|
*reclaimed = false;
|
||||||
mi_segment_t* segment;
|
mi_segment_t* segment;
|
||||||
mi_arena_field_cursor_t current; _mi_arena_field_cursor_init(heap,¤t);
|
mi_arena_field_cursor_t current; _mi_arena_field_cursor_init(heap,¤t);
|
||||||
long max_tries = mi_option_get_clamp(mi_option_max_segment_reclaim, 0, 1024); // limit the work to bound allocation times
|
|
||||||
|
// limit the tries to 10% (default) of the abandoned segments with at least 8 tries, and at most 1024.
|
||||||
|
const size_t perc = (size_t)mi_option_get_clamp(mi_option_max_segment_reclaim, 0, 100);
|
||||||
|
if (perc <= 0) return NULL;
|
||||||
|
const size_t abandoned_count = _mi_arena_segment_abandoned_count();
|
||||||
|
const size_t relative_count = (abandoned_count > 10000 ? (abandoned_count / 100) * perc : (abandoned_count * perc) / 100); // avoid overflow
|
||||||
|
long max_tries = (long)(relative_count < 8 ? 8 : (relative_count > 1024 ? 1024 : relative_count));
|
||||||
while ((max_tries-- > 0) && ((segment = _mi_arena_segment_clear_abandoned_next(¤t)) != NULL))
|
while ((max_tries-- > 0) && ((segment = _mi_arena_segment_clear_abandoned_next(¤t)) != NULL))
|
||||||
{
|
{
|
||||||
segment->abandoned_visits++;
|
segment->abandoned_visits++;
|
||||||
|
|
Loading…
Add table
Reference in a new issue