I use grand central dispatch framework to handle memory pressure change via DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
. This is my program in Objective C:
#import <Foundation/Foundation.h>
#import <dispatch/dispatch.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Starting memory pressure monitoring...");
// Create a dispatch source for memory pressure events
dispatch_source_t memoryPressureSource = dispatch_source_create(
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE,
0,
DISPATCH_MEMORYPRESSURE_WARN |
DISPATCH_MEMORYPRESSURE_CRITICAL |
DISPATCH_MEMORYPRESSURE_NORMAL,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
);
if (memoryPressureSource == NULL) {
NSLog(@"Failed to create dispatch source");
return 1;
}
// Set the event handler block to be executed on memory pressure events
dispatch_source_set_event_handler(memoryPressureSource, ^{
NSLog(@"Memory pressure event handled");
});
dispatch_source_set_registration_handler(memoryPressureSource, ^{
NSLog(@"Memory pressure event registered");
});
dispatch_activate(memoryPressureSource);
// Keep the main thread alive to let the dispatch source process events
dispatch_main();
}
return 0;
}
I compile it via the command:
clang -framework Foundation -framework CoreFoundation -o memory_pressure_tracker ./untitled.mm
and launch it:
./memory_pressure_tracker
At the same time in another terminal I emulate high memory pressure:
sudo memory_pressure -l critical
.
Despite the fact that memory pressure changes in activity monitor, my program does not write any logs about it. The only logs it writes are below:
2024-09-10 10:41:27.048 memory_pressure_tracker[130:11424978] Starting memory pressure monitoring...
2024-09-10 10:41:27.048 memory_pressure_tracker[130:11424985] Memory pressure event registered
Where is the problem?
I tested it on MacOS Sonoma 14.6.1 on M1 Max.
It looks like MacOS is smart enough to not report small spikes in memory pressure and to not notify the apps which can not free some memory because they already use low amount of it.
I've added the following lines to the beginning of main
function to make the app consume some memory:
size_t size = 1024 * 1024 * 1024 / sizeof(int);
int* largeArray = (int*)std::malloc(size * sizeof(int));
for (size_t i = 0; i < size; ++i) {
largeArray[i] = i;
}
In addition, when I emulated critical memory pressure via the command sudo memory_pressure -l critical
which kept allocating memory until pressure becomes critical, I did not get handler called because the pressure came back to normal state immediately.
I managed to get handler called when I emulated pressure for 10 seconds while my test app consumed 1Gb of RAM:
sudo memory_pressure -S -l critical -s 10