mimalloc icon indicating copy to clipboard operation
mimalloc copied to clipboard

mimalloc 2.1.9 does not prioritize allocating memory from huge pages

Open benqwu opened this issue 11 months ago • 5 comments

Hi, I specified the use of huge pages when using mimalloc 2.1.9, and the operating system has enough huge pages available. However, I noticed that upon program startup, 1 GB of memory was allocated from non-hugepage memory first. In version 2.1.7, mimalloc prioritizes allocating memory from hugepage memory until they are exhausted, after which it switches to non-hugepage memory.

The environment variable configuration is as follows: MIMALLOC_SHOW_STATS=1 MIMALLOC_SHOW_ERRORS=1 MIMALLOC_VERBOSE=1 MIMALLOC_RESERVE_HUGE_OS_PAGES=8 MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=0 MIMALLOC_EAGER_COMMIT_DELAY=0

benqwu avatar Jan 06 '25 07:01 benqwu

mi_debug_show_arenas: mimalloc: arena 0: 32 blocks of size 32MiB (in 1 fields) mimalloc: inuse blocks: mimalloc: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx mimalloc: total ('x'): 32 mimalloc: committed blocks: mimalloc: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx mimalloc: total ('x'): 32 mimalloc: arena 1: 256 blocks of size 32MiB (in 4 fields) , pinned mimalloc: inuse blocks: mimalloc: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.............................. mimalloc: ................................................................ mimalloc: ................................................................ mimalloc: ................................................................ mimalloc: total ('x'): 34 mimalloc: total inuse blocks : 66

benqwu avatar Jan 06 '25 08:01 benqwu

Ah I see. I changed the default behavior just before the release -- ouch. Can you try if it is different if you set MIMALLOC_ALLOW_LARGE_OS_PAGES=1 ? Currently, there are 3 modes on Linux based systems:

  • 0 : don't allow large OS pages at all (unless explicitly reserved through huge pages)
  • 1 : actively try to use large OS pages (2 MiB). Only use huge pages when explicitly requested (by reserving huge pages).
  • 2 : allow large OS pages but only through madvise meaning it will use large OS pages when THP is enabled on the system.

In all cases it seems that huge OS pages are only used if explicitly reserved. The reasoning is that using a huge page is a bit "bad" as that memory cannot be shared among other processes or swapped to disk -- so it should only be used if explicitly requested.

I wonder though why you see the initial arena being allocated with huge pages .. it means there is an allocation before the huge arena is reserved?

daanx avatar Jan 06 '25 17:01 daanx

Ah I see. I changed the default behavior just before the release -- ouch. Can you try if it is different if you set MIMALLOC_ALLOW_LARGE_OS_PAGES=1 ? Currently, there are 3 modes on Linux based systems:

  • 0 : don't allow large OS pages at all (unless explicitly reserved through huge pages)
  • 1 : actively try to use large OS pages (2 MiB). Only use huge pages when explicitly requested (by reserving huge pages).
  • 2 : allow large OS pages but only through madvise meaning it will use large OS pages when THP is enabled on the system.

In all cases it seems that huge OS pages are only used if explicitly reserved. The reasoning is that using a huge page is a bit "bad" as that memory cannot be shared among other processes or swapped to disk -- so it should only be used if explicitly requested.

I wonder though why you see the initial arena being allocated with huge pages .. it means there is an allocation before the huge arena is reserved?

The following is the log printed during the startup phase of mimaloc. When specifying the use of 8G of huge page memory, it first allocated 1G of normal memory.

mimalloc: option 'show_errors': 1 mimalloc: option 'show_stats': 1 mimalloc: option 'verbose': 1 mimalloc: option 'eager_commit': 1 mimalloc: option 'arena_eager_commit': 2 mimalloc: option 'purge_decommits': 1 mimalloc: option 'allow_large_os_pages': 2 mimalloc: option 'reserve_huge_os_pages': 8 mimalloc: option 'reserve_huge_os_pages_at': 0 mimalloc: option 'reserve_os_memory': 0 KiB mimalloc: option 'deprecated_segment_cache': 0 mimalloc: option 'deprecated_page_reset': 0 mimalloc: option 'abandoned_page_purge': 0 mimalloc: option 'deprecated_segment_reset': 0 mimalloc: option 'eager_commit_delay': 0 mimalloc: option 'purge_delay': 10 mimalloc: option 'use_numa_nodes': 0 mimalloc: option 'disallow_os_alloc': 0 mimalloc: option 'os_tag': 100 mimalloc: option 'max_errors': 32 mimalloc: option 'max_warnings': 32 mimalloc: option 'max_segment_reclaim': 10 mimalloc: option 'destroy_on_exit': 0 mimalloc: option 'arena_reserve': 1048576 KiB mimalloc: option 'arena_purge_mult': 10 mimalloc: option 'purge_extend_delay': 1 mimalloc: option 'abandoned_reclaim_on_free': 0 mimalloc: option 'disallow_arena_alloc': 0 mimalloc: option 'retry_on_oom': 400 mimalloc: option 'visit_abandoned': 0 mimalloc: option 'guarded_min': 0 mimalloc: option 'guarded_max': 1073741824 mimalloc: option 'guarded_precise': 0 mimalloc: option 'guarded_sample_rate': 0 mimalloc: option 'guarded_sample_seed': 0 mimalloc: option 'target_segments_per_thread': 0 mimalloc: process init: 0x7FAE415AA740 mimalloc: using 2 numa regions mimalloc: reserved 1048576 KiB memory //Does this indicate that it first allocated 1G of normal memory? mimalloc: secure level: 0 mimalloc: mem tracking: none mimalloc: numa node 0: reserved 8 GiB huge pages (of the 8 GiB requested)

If memory allocation is strictly limited to huge page memory, the program will fail to allocate memory in case of an overflow during runtime. Therefore, I want mimalloc to prioritize allocating from huge pages (for performance reasons) but allow it to fall back to normal memory if huge page memory is exhausted during runtime. In version 2.1.7, mimalloc's behavior aligns with this requirement. In version 2.1.9, is there any explicit configuration to achieve the same effect?

benqwu avatar Jan 07 '25 01:01 benqwu

Ah I see. I changed the default behavior just before the release -- ouch. Can you try if it is different if you set MIMALLOC_ALLOW_LARGE_OS_PAGES=1 ? Currently, there are 3 modes on Linux based systems:

  • 0 : don't allow large OS pages at all (unless explicitly reserved through huge pages)
  • 1 : actively try to use large OS pages (2 MiB). Only use huge pages when explicitly requested (by reserving huge pages).
  • 2 : allow large OS pages but only through madvise meaning it will use large OS pages when THP is enabled on the system.

In all cases it seems that huge OS pages are only used if explicitly reserved. The reasoning is that using a huge page is a bit "bad" as that memory cannot be shared among other processes or swapped to disk -- so it should only be used if explicitly requested.

I wonder though why you see the initial arena being allocated with huge pages .. it means there is an allocation before the huge arena is reserved?

I try MIMALLOC_ALLOW_LARGE_OS_PAGES=1 but the result still didn't change.

benqwu avatar Jan 08 '25 08:01 benqwu

In all cases it seems that huge OS pages are only used if explicitly reserved. The reasoning is that using a huge page is a bit "bad" as that memory cannot be shared among other processes or swapped to disk -- so it should only be used if explicitly requested.

Hi @daanx, is it possible adding an option that allows:

  1. Prioritize reserved huge OS pages (1GiB).
  2. If exhausted, fall back to large OS pages (2 MiB).

or could you point out how I can achieve that?

Besides, is there any function to easily malloc directly into huge OS pages? (I searched through the docs but failed finding one.)

GoldJohnKing avatar Feb 14 '25 03:02 GoldJohnKing