Re: Strange Memory Patterns


Sandor Szatmari
 

Jonathan,

Thanks for the solution of sending events to perturb the main runloop.  With a little googling, I adapted your solution as follows…

Cheers!

double delayInSeconds = 2.0;

dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,

0,

0,

dispatch_get_main_queue());

void (^memorySentinel)(void) = ^()

{

NSLog( @"I'm firing!" );

NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined

location:NSZeroPoint

  modifierFlags:0

  timestamp:[NSDate timeIntervalSinceReferenceDate]

windowNumber:0

context:nil

subtype:0

  data1:0

  data2:0];

[NSApp postEvent:event

atStart:YES];

};

if (timer)

{

dispatch_source_set_timer(timer,

  dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC),

  delayInSeconds * NSEC_PER_SEC,

  (1ull * NSEC_PER_SEC) / 10);

dispatch_source_set_event_handler(timer, memorySentinel);

dispatch_resume(timer);

}

else

{

// tell someone?

}


Sandor

On Apr 25, 2019, at 04:44, Jonathan Taylor <jonathan.taylor@...> wrote:

This sounds very similar to problems I have encountered myself.

Issue 1: GCD callbacks are part of an autorelease pool, but you can't rely on it getting drained in a reliable manner, so wrap your callbacks with your own explicit pool.

Issue 2: Background apps do not seem to always have their main thread autorelease pools drained reliably. A snippet of code I've posted a few times over the years:

// Create a periodic timer that "tickles" the main event loop to drain autorelease pools.
// Response from cocoa-dev discussion was that:
//  This is a long-standing problem with AppKit. According to the documentation,
//  "The Application Kit creates an autorelease pool on the main thread at the
//  beginning of every cycle of the event loop, and drains it at the end, thereby
//  releasing any autoreleased objects generated while processing an event."
//  However, this is somewhat misleading. The "end" of the event loop cycle is
//   immediately before the beginning. Thus, for example, if your app is in the background
//   and not receiving events, then the autorelease pool will not be drained. That's why
//   your memory drops significantly when you click the mouse or switch applications.
[JDispatchTimer allocRepeatingTimerOnQueue:dispatch_get_main_queue() atInterval:5.0 withHandler:^{
NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint modifierFlags:0 timestamp:[NSDate timeIntervalSinceReferenceDatewindowNumber:0 context:nil subtype:0 data1:0 data2:0];
[NSApp postEvent:event atStart:YES];
}];
 
 

Join cocoa@apple-dev.groups.io to automatically receive all group messages.