How can mimalloc manage a piece of allocated memory?
I have already allocated a piece of big memory by mmap, the memory size (as MEM_SIZE) is large, so I want to use it as a memory pool, or a heap, so that I can use the memory efficiently. For example, every time I want a piece of memory (large but not larger than MEM_SIZE), I can just easily use a function to allocate and get a void *, and release this pointer later, and the pool/heap can collect this memory. An example:
// allocate memory
void* mem_ptr = mmap(NULL, MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// create a heap or memory pool based on the allocated memory
// is there a function works as create_heap(...)?
auto my_heap = create_heap(mem_ptr, MEM_SIZE);
// when I need to get some memory
void* mem_for_var1 = alloc(my_heap, mem_size_for_var1);
auto var1 = new (mem_for_var1) float();
// use var1
// release
...
And if there exists any memory allocator or memory pool library for C++ that can work as above, it is appreciated if you could tell me and leave some examples or the documents of it.
Yes, mimalloc has mi_manage_os_memory for this purpose:
bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node);
This will add the memory area to the mimalloc arena's from which it will allocate its memory (use numa_node=-1 for no NUMA preference). There is no need for a specific heap, just mi_malloc will work. It is best if the area is as large as possible such that mimalloc can manage it most effectively with regard to fragmentation.
Hope this helps, Daan
ps. There is also an extended api, mi_manage_os_memory_ex
to reserve "exclusive" memory that can only be used with heaps attached to such memory (mi_heap_new_in_arena) but I don't think that is what you are asking? (this is used for example to implement compressed pointers in the Koka language using a 4GiB exclusive area for language allocations)
Thanks very much for your help! It really does me a favor. mimalloc is very useful, and my project cannot be done without it.
@daanx I am a bit confused about how the mimalloc uses the process memory initially. As far as I know, when the process starts, it already reserves some memory area for the heap, and libc uses sbrk to extend.
But I can track mimalloc down, I understand that it does mmap do manage the memory, right?
Also, what is the alignment-requirement for the mimalloc?
Ah, mimalloc generally does not use sbrk (as that doesn't allow returning (purging) memory back to the OS), and we try to use mmap on most unix systems. See https://github.com/microsoft/mimalloc/blob/dev/src/prim/unix/prim.c for the primitives. Mimalloc allocates it's OS memory with 4MiB alignment (on 64-bit systems).
thank you for the clarification!
Hi @daanx
Thank you for having responded in the issue and similar issues.
I have a similar problem to the OP, and I can't get mimalloc to allocate from the mmapped file, even with mi_reserve_os_memory...
Here's the code (I've removed sanity and error message checks for brevity)
#define FILE_SIZE (16 * 1024 * 1024) // 16MB
fd = open("mmapped_file.txt", O_RDWR | O_CREAT, 0666);
char *file_in_memory = mmap(NULL, FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_32BIT, fd, 0);
int reserveRet = mi_reserve_os_memory(FILE_SIZE, false, true);
int manageRet = mi_manage_os_memory(file_in_memory, FILE_SIZE, true, false, false, -1);
void *p = mi_malloc(1 * 1024 * 1024); // 1MB
void *q = mi_malloc(1 * 1024 * 1024); // 1MB
void *r = mi_malloc(1 * 1024 * 1024); // 1MB
void *s = mi_malloc(1 * 1024 * 1024); // 1MB
printf("base: %p\n", file_in_memory);
printf("p : %p\n", p);
printf("q : %p\n", q);
printf("r : %p\n", r);
printf("s : %p\n", s);
Outputs:
base: 0x40000000
p : 0x20000000200
q : 0x20000140200
r : 0x20000280200
s : 0x20000400200
How do I make sure mimalloc is using my mmapped file?
I'll try your solution in #730 next, but I'm not sure where to find MIMALLOC_RESERVE_OS_MEMORY or MIMALLOC_LIMIT_OS_ALLOC
Edit: The #730 solution didn't work either, sadly. Iused mi_reserve_os_memory_ex and mi_heap_new_in_arena as well as mi_heap_set_default and mi_heap_malloc as instructed, and they're returning valid values (no errors).