make reclaim tries a percentage of the abandoned count
This commit is contained in:
parent
cf8f73098e
commit
c4f1f2e079
@ -126,6 +126,7 @@ void _mi_arena_unsafe_destroy_all(mi_stats_t* stats);
|
||||
|
||||
bool _mi_arena_segment_clear_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
|
||||
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
|
||||
(and crosses the arena API but it is convenient to have here).
|
||||
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
|
||||
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;
|
||||
|
||||
size_t _mi_arena_segment_abandoned_count(void) {
|
||||
return mi_atomic_load_relaxed(&abandoned_count);
|
||||
}
|
||||
|
||||
// reclaim a specific abandoned segment; `true` on success.
|
||||
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
|
||||
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_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
|
||||
// initialize committed bitmap?
|
||||
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
|
||||
{ 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_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!
|
||||
#if (MI_INTPTR_SIZE>4)
|
||||
{ 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;
|
||||
mi_segment_t* segment;
|
||||
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))
|
||||
{
|
||||
segment->abandoned_visits++;
|
||||
|
Loading…
Reference in New Issue
Block a user