Running out of memory in 'Other Processes' in Usage Comparion Xcode iOS9
Asked Answered
E

2

10

My app crashes on devices with 0.5GB memory. However, profiling memory usage in Xcode - it rarely goes above 140MB. I've used instruments to check leaks and there are none that are significant.

However, when I run my app, the memory used by 'Other Processes' is always very high. This is the resting state after launching:

enter image description here

I added a 1 second delay in each cycle of a loop in my code, and discovered that on each loop, the 'other processes' increases memory usage by about 3MB per object, until on 0.5GB devices, it runs out and crashes.

enter image description here

This question suggests that these are other apps using that memory, but I have closed every other app and the usage directly correlates with my looping code.

What could be using memory in other processes, that is actually running in my app? And why is my 'Other Processes' using up so much memory?

To give an idea of what I'm doing, I'm pulling data from Parse, then looping through each of the objects returned and creating an SKNode subclass object from the data. I add this node to an array, (for reference) and to the scene. Here's the code I'm doing on the main thread with the delay added. NB the line:

self drawRelationships:[_batches objectAtIndex:_index] forMini:_playerMini];

Is a BFTask and so asynchronous. And I'm dividing the array into smaller batches so I can see incremental memory usage, as each batch is drawn. If I try to draw the whole lot at once, OOM occurs immediately...

- (void)drawNewRelationships
{
    _batches = [NSMutableArray array];
    _index = 0;

    [_playerMini fetchInBackgroundWithBlock:^(PFObject *object, NSError *error) {
        [ParseQuery getNewRelationshipsForMini:_playerMini current:_miniRows.relationshipIds withBlock:^(NSMutableArray *newRelationships) {
            _batches = [self batchArrays:3 fromArray:newRelationships];
            _index = 0;
            [self drawBatches];
        }];
    }];
}

- (void)drawBatches
{
    if ([_batches objectAtIndex:_index]) {
        [self drawRelationships:[_batches objectAtIndex:_index] forMini:_playerMini];
        _index++;
        if (_index < [_batches count]) {
            [self performSelector:@selector(drawBatches) withObject:nil afterDelay:1];
        }
    }
}

The node contains other data, (a couple of arrays, custom object) and I've tried running the app with all that data removed. I've tried running on the main thread and background threads. I've tried using BFTask to do things asynchronously. Everything I've tried ends up with the same behaviour - creating these SKNode objects eats up memory in 'Other Processes', until on low memory devices, it crashes.

It might be worth noting, that this behaviour has only started to occur since iOS9.

Basically, what can be using all this memory in 'other processes' and how can I free it?

Update

I've tried running the Sprite Kit sample app, and even that uses ~550MB in other processes when it launches. Could this be a major Sprite Kit bug?

enter image description here

Etherize answered 26/10, 2015 at 15:27 Comment(5)
Can you please expand your paragraph beginning "To give an idea of what I'm doing…" with the actual code? It might give more insight.Chitwood
You could also try using autoreleasepool to free up memory during the looping process.Chitwood
@AaronBrager Ok - I'll look in to releasing the autoreleasepool for Objective-c... There is a lot of code I'd have to add to give a clear picture, and I'm not sure it's relevant, since this problem occurs in the sample project too. I was hoping there might be a more top down solutionEtherize
@AaronBrager Ok I've added some code. I checked out this on autoreleasepools: #9087413 but not sure where I can use this. I tried adding the nodes inside an autoreleasepool but the other process memory is still consumed.Etherize
It's hard to understand what you're doing based on the code (some of the methods you call are missing). But it looks like you have a lot of code dedicated to maintaining the order things get done in, and you might be building up a really big stack in the process. Consider rewriting this stuff using NSOperationQueue - you can add each separate chunk of work as an NSBlockOperation, throttle how much is done at once, and get notified when the work is complete.Chitwood
E
2

Well it turned out to be a rather specific issue. The memory allocated to other processes was in fact memory leaking from my app. It occurred when I flattened a node with many children, but didn't nil an NSDictionary that contained references to all the pre-flattened nodes. For some reason, this mem leak didn't show up when profiling.

I also found a very good blog post: http://battleofbrothers.com/sirryan/memory-usage-in-sprite-kit on reducing your app's memory footprint. Worth a read if you're trying to optimise.

Etherize answered 29/10, 2015 at 15:1 Comment(0)
K
1

I want to provide a solution for those who are not necessarily using SpriteKit, but are facing issues with Other Processes taking up more and more memory - meaning there is a leak. This is the best way I've found to debug leaks in 'Other processes' so far.

  1. Open Instruments, select Activity Monitor
  2. Reproduce the steps in your application, see which process is taking ownership for the leak. For example if it is mediaserverd, you probably have a leak revolving around encoding/decoding or something media related, so things like releasing buffers or releasing the decompression session might not be working as planned.
  3. Now that you have an idea of where to look, open Xcode and use the Debug Memory Graph tool, and look for the potential leaking instances, and you should see all the strong references towards it. For myself working a lot in objective-c++ it turns out to be missing autoreleasepools quite often.
Kerry answered 8/5, 2020 at 15:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.