Memory leaks with SKTextures and PlaySound

Hello,


So, I'm making a very small puzzle game, which requires loading a ton of images on screen, and when a user aligns them, they get dismissed (removed) and new images are added to the sceen.


Coding wise, nothing special. But I allow the user to go back to the main screen or levels selections, where he can go to another level.

Tha main problem is that every asset loaded into memory isn't freed at all.


I tried writing some code in the deinit, to see if it's correctly called or not, and it's correctly called.

I have no strong reference, and I double check by emptying any var and nilling them in the deinit. I added a method on the main view controller to present a nil scene after I leave the game level, and while it helps a bit, the memory isn't freed at all.

After playing two or three levels, the device becomes impossibly slow and unresponsive.


The culprit seems to be the way I load textures, which I tried many but settlked now for:

SKSpriteNode(texture: SKTextureAtlas(named:).textureNamed())

Then I add the node to the scene. And in the deinit, I loop through all the nodes and remove them, then do removeAllActions(), removeAllChildren() and removeFromParent() ... but it still doesn't empty the memory.


Is there any way to free the cache?

- Triggering a memory warning after leaving the level frees about 50% of the memory

- Checking under Instruments reveals no memory leak, although the memory usage climbs indefinitely, and when checking memory, 90% of it is in VM:CoreUI image data, and checking every entry, it's the same [_CSIRenditionBlockData _allocateImageBytes] that comes back.

Well, as you've guessed, SpriteKit does use a texture cache that it manages on it's own. It's pretty normal to see the memory usage grow and as far as I know, nope, you don't have any control over it. Can you give a sense of how many pictures you have on screen at a time, their size, and how many you have on storage to pick from to get a rough idea ?


My guess though is that your issue is related to the usage of texture atlases. How are your images organized ? Since you mention you pick from many, do you actually have several of them from which to pick your pictures ?


The point of a TextureAtlas is to fit as many texture as you can, tetris style if you will, in one up to 4Kx4K GPU texture. The way you usually use them is to fit your stuff in an atlas, preload it all, then use at will from it. See this link : https://developer.apple.com/library/ios/recipes/xcode_help-texture_atlas/AboutTextureAtlases/AboutTextureAtlases.html#//apple_ref/doc/uid/TP40013290-CH2-SW1


If you have many of them, for organizational purpose, and you load one picture from each, you are going against the spirit of what they are supposed to do by needing to load the whole sprite sheet every time, and need to keep it in memory even if you only use one.


Either you can preload them all, and use them as is (which will be very fast), or you should consider using individual files and load them as you go, which will then be managed in a more traditional fashion by the texture cache.

Hi,


Thanks for the answer.


I know what the atlas purpose is, and I'm using it in accordance with Apple's documentation, and hopefully, best practices.

I do have multiple atlases for some organizational purposes, but I'd say I'm mostly using 2 atlases at the same time:

- One that has the grid elements (about 15 images, 240x240 transparent PNGs for @2x)

- One that has the puzzle elements (about two sets of 8 elements, one normal and one highlighted set, same as above 240x240 transparent PNGs for the @2x version).


So, one scene is basically a view controller with HUD elements loaded from an assets catalog (PDF vectors, assembled via IB), and a square SpriteKit scene in the center that contains the puzzle.

The puzzle is a 10x10 grid on two levels, one with the grid tiles, and on top, elements.

Elements (SKNodes) are generated and destroyed following player's actions.


(For a better idea, the Candy Crush tutorial on Ray Wenderlich's website is the closest thing, although that one has the whole scene as a SpriteKit scene).



The problem is that dismissing the view doesn't free the memory at all. And no matter how much I I debug with instruments, there is no memory leak detected, and all the growths are images (in CoreUI [_CSIRenditionBlockData _allocateImageBytes]).

Simulating a memory warning does free a big chunk of the memory ... But ingame, the game slows down and become unplayable without throwing any memory warning.

How many "puzzle" texture atlases do you have total ? 1 per level ?

SKScene life cycles can be weird in my experience. One thing that did help me a lot with memory management is loading textures from a singleton. I'd suggest you consider that option. You could also try not using texture atlases as a last resort to compare memory usage.

Others may have better suggestions.

Memory leaks with SKTextures and PlaySound
 
 
Q