mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 23:39:31 +03:00
clean up options
This commit is contained in:
parent
932f866105
commit
4e65b5018f
4 changed files with 51 additions and 45 deletions
|
@ -811,9 +811,8 @@ typedef enum mi_option_e {
|
|||
mi_option_segment_cache, ///< The number of segments per thread to keep cached.
|
||||
mi_option_page_reset, ///< Reset page memory after \a mi_option_reset_delay milliseconds when it becomes free.
|
||||
mi_option_segment_reset, ///< Experimental
|
||||
mi_option_reset_delay, ///< Delay in milli-seconds before resetting a page (100ms by default)
|
||||
mi_option_decommit_delay, ///< Delay in milli-seconds before decommitting currently unused reserved memory (25ms by default)
|
||||
mi_option_use_numa_nodes, ///< Pretend there are at most N NUMA nodes
|
||||
mi_option_reset_decommits, ///< Experimental
|
||||
mi_option_eager_commit_delay, ///< Experimental
|
||||
mi_option_os_tag, ///< OS tag to assign to mimalloc'd memory
|
||||
_mi_option_last
|
||||
|
@ -1068,7 +1067,7 @@ or via environment variables.
|
|||
- `MIMALLOC_PAGE_RESET=0`: by default, mimalloc will reset (or purge) OS pages when not in use to signal to the OS
|
||||
that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server)
|
||||
programs. By setting it to `0` no such page resets will be done which can improve performance for programs that are not long
|
||||
running. As an alternative, the `MIMALLOC_RESET_DELAY=`<msecs> can be set higher (100ms by default) to make the page
|
||||
running. As an alternative, the `MIMALLOC_DECOMMIT_DELAY=`<msecs> can be set higher (100ms by default) to make the page
|
||||
reset occur less frequently instead of turning it off completely.
|
||||
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages (2MiB) when available; for some workloads this can significantly
|
||||
improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs
|
||||
|
|
|
@ -306,27 +306,28 @@ typedef enum mi_option_e {
|
|||
mi_option_show_errors,
|
||||
mi_option_show_stats,
|
||||
mi_option_verbose,
|
||||
// the following options are experimental
|
||||
// some of the following options are experimental
|
||||
// (deprecated options are kept for binary backward compatibility with v1.x versions)
|
||||
mi_option_eager_commit,
|
||||
mi_option_eager_region_commit,
|
||||
mi_option_reset_decommits,
|
||||
mi_option_deprecated_eager_region_commit,
|
||||
mi_option_deprecated_reset_decommits,
|
||||
mi_option_large_os_pages, // implies eager commit
|
||||
mi_option_reserve_huge_os_pages,
|
||||
mi_option_reserve_huge_os_pages_at,
|
||||
mi_option_reserve_os_memory,
|
||||
mi_option_segment_cache,
|
||||
mi_option_page_reset,
|
||||
mi_option_abandoned_page_reset,
|
||||
mi_option_segment_reset,
|
||||
mi_option_abandoned_page_decommit,
|
||||
mi_option_deprecated_segment_reset,
|
||||
mi_option_eager_commit_delay,
|
||||
mi_option_allow_decommit,
|
||||
mi_option_reset_delay,
|
||||
mi_option_segment_decommit_delay,
|
||||
mi_option_decommit_delay,
|
||||
mi_option_use_numa_nodes,
|
||||
mi_option_limit_os_alloc,
|
||||
mi_option_os_tag,
|
||||
mi_option_max_errors,
|
||||
mi_option_max_warnings,
|
||||
mi_option_allow_decommit,
|
||||
mi_option_segment_decommit_delay,
|
||||
_mi_option_last
|
||||
} mi_option_t;
|
||||
|
||||
|
|
|
@ -49,54 +49,50 @@ typedef struct mi_option_desc_s {
|
|||
mi_init_t init; // is it initialized yet? (from the environment)
|
||||
mi_option_t option; // for debugging: the option index should match the option
|
||||
const char* name; // option name without `mimalloc_` prefix
|
||||
const char* legacy_name; // potential legacy v1.x option name
|
||||
} mi_option_desc_t;
|
||||
|
||||
#define MI_OPTION(opt) mi_option_##opt, #opt
|
||||
#define MI_OPTION_DESC(opt) {0, UNINIT, MI_OPTION(opt) }
|
||||
#define MI_OPTION(opt) mi_option_##opt, #opt, NULL
|
||||
#define MI_OPTION_LEGACY(opt,legacy) mi_option_##opt, #opt, #legacy
|
||||
|
||||
static mi_option_desc_t options[_mi_option_last] =
|
||||
{
|
||||
// stable options
|
||||
#if MI_DEBUG || defined(MI_SHOW_ERRORS)
|
||||
#if MI_DEBUG || defined(MI_SHOW_ERRORS)
|
||||
{ 1, UNINIT, MI_OPTION(show_errors) },
|
||||
#else
|
||||
#else
|
||||
{ 0, UNINIT, MI_OPTION(show_errors) },
|
||||
#endif
|
||||
#endif
|
||||
{ 0, UNINIT, MI_OPTION(show_stats) },
|
||||
{ 0, UNINIT, MI_OPTION(verbose) },
|
||||
|
||||
// the following options are experimental and not all combinations make sense.
|
||||
// Some of the following options are experimental and not all combinations are valid. Use with care.
|
||||
{ 1, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (8MiB) (but see also `eager_commit_delay`)
|
||||
#if defined(_WIN32) || (MI_INTPTR_SIZE <= 4) // and other OS's without overcommit?
|
||||
{ 0, UNINIT, MI_OPTION(eager_region_commit) },
|
||||
{ 0, UNINIT, MI_OPTION(reset_decommits) }, // reset decommits memory
|
||||
#else
|
||||
{ 1, UNINIT, MI_OPTION(eager_region_commit) },
|
||||
{ 0, UNINIT, MI_OPTION(reset_decommits) }, // legacy; ignored now and reset always uses MADV_FREE/MADV_DONTNEED (issue #518)
|
||||
#endif
|
||||
{ 0, UNINIT, MI_OPTION(deprecated_eager_region_commit) },
|
||||
{ 0, UNINIT, MI_OPTION(deprecated_reset_decommits) },
|
||||
{ 0, UNINIT, MI_OPTION(large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's
|
||||
{ 0, UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages
|
||||
{ -1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N
|
||||
{ 0, UNINIT, MI_OPTION(reserve_os_memory) },
|
||||
{ 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread
|
||||
{ 0, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free
|
||||
{ 0, UNINIT, MI_OPTION(abandoned_page_reset) },// reset free page memory when a thread terminates
|
||||
{ 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free (needs eager commit)
|
||||
#if defined(__NetBSD__)
|
||||
{ 0, UNINIT, MI_OPTION_LEGACY(abandoned_page_decommit, abandoned_page_reset) },// decommit free page memory when a thread terminates
|
||||
{ 0, UNINIT, MI_OPTION(deprecated_segment_reset) },
|
||||
#if defined(__NetBSD__)
|
||||
{ 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
|
||||
#elif defined(_WIN32)
|
||||
#elif defined(_WIN32)
|
||||
{ 4, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
|
||||
#else
|
||||
#else
|
||||
{ 1, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
|
||||
#endif
|
||||
{ 1, UNINIT, MI_OPTION(allow_decommit) }, // decommit slices when no longer used (after reset_delay milli-seconds)
|
||||
{ 25, UNINIT, MI_OPTION(reset_delay) }, // page reset delay in milli-seconds (= decommit)
|
||||
{ 500, UNINIT, MI_OPTION(segment_decommit_delay) },// decommit delay in milli-seconds for freed segments
|
||||
#endif
|
||||
{ 25, UNINIT, MI_OPTION_LEGACY(decommit_delay, reset_delay) }, // page decommit delay in milli-seconds
|
||||
{ 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes.
|
||||
{ 0, UNINIT, MI_OPTION(limit_os_alloc) }, // 1 = do not use OS memory for allocation (but only reserved arenas)
|
||||
{ 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_warnings) }, // maximum warnings that are output
|
||||
{ 1, UNINIT, MI_OPTION(allow_decommit) }, // decommit slices when no longer used (after decommit_delay milli-seconds)
|
||||
{ 500, UNINIT, MI_OPTION(segment_decommit_delay) } // decommit delay in milli-seconds for freed segments
|
||||
};
|
||||
|
||||
static void mi_option_init(mi_option_desc_t* desc);
|
||||
|
@ -526,11 +522,21 @@ static bool mi_getenv(const char* name, char* result, size_t result_size) {
|
|||
|
||||
static void mi_option_init(mi_option_desc_t* desc) {
|
||||
// Read option value from the environment
|
||||
char s[64+1];
|
||||
char buf[64+1];
|
||||
mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
||||
mi_strlcat(buf, desc->name, sizeof(buf));
|
||||
char s[64+1];
|
||||
if (mi_getenv(buf, s, sizeof(s))) {
|
||||
bool found = mi_getenv(buf,s,sizeof(s));
|
||||
if (!found && desc->legacy_name != NULL) {
|
||||
mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
||||
mi_strlcat(buf, desc->legacy_name, sizeof(buf));
|
||||
found = mi_getenv(buf,s,sizeof(s));
|
||||
if (found) {
|
||||
_mi_warning_message("environment option \"mimalloc_%s\" is deprecated -- use \"mimalloc_%s\" instead.\n", desc->legacy_name, desc->name );
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
size_t len = strlen(s);
|
||||
if (len >= sizeof(buf)) len = sizeof(buf) - 1;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
|
|
|
@ -538,7 +538,7 @@ static bool mi_segment_commitx(mi_segment_t* segment, bool commit, uint8_t* p, s
|
|||
}
|
||||
// increase expiration of reusing part of the delayed decommit
|
||||
if (commit && mi_commit_mask_any_set(&segment->decommit_mask, &mask)) {
|
||||
segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_reset_delay);
|
||||
segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_decommit_delay);
|
||||
}
|
||||
// always undo delayed decommits
|
||||
mi_commit_mask_clear(&segment->decommit_mask, &mask);
|
||||
|
@ -554,7 +554,7 @@ static bool mi_segment_ensure_committed(mi_segment_t* segment, uint8_t* p, size_
|
|||
|
||||
static void mi_segment_perhaps_decommit(mi_segment_t* segment, uint8_t* p, size_t size, mi_stats_t* stats) {
|
||||
if (!segment->allow_decommit) return;
|
||||
if (mi_option_get(mi_option_reset_delay) == 0) {
|
||||
if (mi_option_get(mi_option_decommit_delay) == 0) {
|
||||
mi_segment_commitx(segment, false, p, size, stats);
|
||||
}
|
||||
else {
|
||||
|
@ -569,21 +569,21 @@ static void mi_segment_perhaps_decommit(mi_segment_t* segment, uint8_t* p, size_
|
|||
mi_commit_mask_t cmask;
|
||||
mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask); // only decommit what is committed; span_free may try to decommit more
|
||||
mi_commit_mask_set(&segment->decommit_mask, &cmask);
|
||||
segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_reset_delay);
|
||||
segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_decommit_delay);
|
||||
mi_msecs_t now = _mi_clock_now();
|
||||
if (segment->decommit_expire == 0) {
|
||||
// no previous decommits, initialize now
|
||||
mi_assert_internal(mi_commit_mask_is_empty(&segment->decommit_mask));
|
||||
segment->decommit_expire = now + mi_option_get(mi_option_reset_delay);
|
||||
segment->decommit_expire = now + mi_option_get(mi_option_decommit_delay);
|
||||
}
|
||||
else if (segment->decommit_expire <= now) {
|
||||
// previous decommit mask already expired
|
||||
// mi_segment_delayed_decommit(segment, true, stats);
|
||||
segment->decommit_expire = now + (mi_option_get(mi_option_reset_delay) / 8); // wait a tiny bit longer in case there is a series of free's
|
||||
segment->decommit_expire = now + (mi_option_get(mi_option_decommit_delay) / 8); // wait a tiny bit longer in case there is a series of free's
|
||||
}
|
||||
else {
|
||||
// previous decommit mask is not yet expired
|
||||
// segment->decommit_expire += 2; // = now + mi_option_get(mi_option_reset_delay);
|
||||
// segment->decommit_expire += 2; // = now + mi_option_get(mi_option_decommit_delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -877,7 +877,7 @@ static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_
|
|||
segment->commit_mask = commit_mask; // on lazy commit, the initial part is always committed
|
||||
segment->allow_decommit = (mi_option_is_enabled(mi_option_allow_decommit) && !segment->mem_is_pinned && !segment->mem_is_large);
|
||||
if (segment->allow_decommit) {
|
||||
segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_reset_delay);
|
||||
segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_decommit_delay);
|
||||
segment->decommit_mask = decommit_mask;
|
||||
mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask));
|
||||
#if MI_DEBUG>2
|
||||
|
@ -1245,7 +1245,7 @@ static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) {
|
|||
}
|
||||
|
||||
// perform delayed decommits
|
||||
mi_segment_delayed_decommit(segment, mi_option_is_enabled(mi_option_abandoned_page_reset) /* force? */, tld->stats);
|
||||
mi_segment_delayed_decommit(segment, mi_option_is_enabled(mi_option_abandoned_page_decommit) /* force? */, tld->stats);
|
||||
|
||||
// all pages in the segment are abandoned; add it to the abandoned list
|
||||
_mi_stat_increase(&tld->stats->segments_abandoned, 1);
|
||||
|
|
Loading…
Add table
Reference in a new issue