Hello I was wondering if there is a way to ensure that a C program I am writing can only write to 1 virtual page. I am trying to test how space efficient different Mallocs are and I need a way to ensure that the OS will not try to swap out pages making the space efficiency test pointless. I am on Mac OS Sonoma v14.5.
OK.
Are you trying measure the behaviour of the system malloc
implementation? Or implement your own malloc
and measure it’s behaviour?
You can’t force the system malloc
implementation to use a specific VM address range but, even if you could, the results are unlikely to be what you’d expect. The system memory allocator is super complex. It uses a variety of suballocation techniques to improve it’s performance — both speed and memory efficiency — in the face of the serious pressure put on it by your typical Mac app. Those techniques mean there you can’t reasonably measure it’s efficiency using the approach you’ve described.
Consider this program:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
#pragma unused(argc)
#pragma unused(argv)
void * mem1 = calloc(1, 1);
void * mem24 = calloc(1, 24);
void * mem3900 = calloc(1, 3900);
void * mem256k = calloc(1, 256 * 1024);
void * mem100m = calloc(1, 100 * 1024 * 1024);
fprintf(stderr, " mem1: %p\n", mem1);
fprintf(stderr, " mem24: %p\n", mem24);
fprintf(stderr, "mem3900: %p\n", mem3900);
fprintf(stderr, "mem256k: %p\n", mem256k);
fprintf(stderr, "mem100m: %p\n", mem100m);
fprintf(stderr, "pausing, pid: %d\n", (int) getpid());
pause();
return EXIT_SUCCESS;
}
I ran this on my Mac and got this:
% ./Test776021
mem1: 0x600000548030
mem24: 0x60000074d260
mem3900: 0x136008800
mem256k: 0x138008000
mem100m: 0x125e00000
pausing, pid: 84342
I then ran vmmap
against the process. The output is complex, so I’ve done some significant editing to fit it into this post:
% vmmap 84342
…
==== Writable regions for process 84342
REGION TYPE START - END … REGION DETAIL
…
MALLOC_LARGE (reserved) 125e00000-12c200000 … MallocHelperZone_0x104e4c000
…
MALLOC_SMALL 136000000-136800000 … MallocHelperZone_0x104e4c000
MALLOC_MEDIUM 138000000-140000000 … MallocHelperZone_0x104e4c000
…
MALLOC_NANO 600000000000-600020000000 … DefaultMallocZone_0x104e94000
…
You can see:
-
mem1
andmem24
were both suballocated from a large chunk of address space labelledMALLOC_NANO
. Such chunks of address space are called allocation zones. -
mem3900
was suballocated from aMALLOC_SMALL
zone. -
mem256k
was suballocated from aMALLOC_MEDIUM
zone. -
mem100m
was large enough thatmalloc
went straight to the kernel, resulting aMALLOC_LARGE
zone that contains a single item.
If you want to measure the efficiency of the system memory allocator, you can use tools like vmmap
and heap
to do that. But it’s gonna be very hard to compare those results with other allocators. There’s simply no way to configure it to behave in some sort of ‘standard’ way.
If you want to write your own memory allocators and compare the behaviour of each, that’s quite feasible. Lemme know in that case and I can help you get started on that path.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"