Search code examples
objective-cmacosgrand-central-dispatch

Memory pressure detection is not working on MacOS


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.


Solution

  • 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