Memory pressure change not always reported

On macOS (checked on 10.11 & 10.12), if I track memory pressure changes with code like


_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, 0, DISPATCH_MEMORYPRESSURE_NORMAL | DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0));

__weak typeof(self) weakSelf = self;

dispatch_source_set_event_handler(_source, ^{

typeof(self) strongSelf = weakSelf;

dispatch_source_memorypressure_flags_t pressureLevel = dispatch_source_get_data(strongSelf.source);

NSLog(@"Memory pressure level: %lu", pressureLevel);

});

dispatch_resume(_source);



and use the memory_pressure command line tool, or use a virtual machine to simulate different RAM usage scenarios, I notice I will indeed get DISPATCH_MEMORYPRESSURE_WARN and DISPATCH_MEMORYPRESSURE_CRITICAL memory pressure changes, but I never receive DISPATCH_MEMORYPRESSURE_NORMAL when it goes back to normal.


Also, if an application is started while the memory pressure is already in an elevated state, it will never report that with this mechanism. There is no means to obtain the memory pressure "right now".


Is there an accurate method to get the correct memory pressure on macOS?

Replies

It is possible to query the current memory pressure level using sysctl:


`error = sysctlbyname("kern.memorystatus_vm_pressure_level", &current_level, &length, NULL, 0);`


The value returned will map to the `dispatch_source_memorypressure_flags_t` values.


On iOS at least this works in the simulator, but on the iOS device hardware it will return "Operation not permitted". You may have a similar experience with a sandboxed macOS app, but that is just a guess on my part.


I filed radar 37470391 describing this behavior on iOS and radar 37470568 as an enhancement asking for a high level API for getting the current memory pressure level.