SpriteKit Memory Leak on static Menu scene - ios

Im experiencing memory leak on static menu scene, it appears that it happens on every scene, game scene itself but also static menu/gameover. Memory appears to be deallocated correctly (and it's reduced when scene is gone).
Those static scenes does not conatins even update callback defined.
It's all setup in didMoveToView and inside it there are couple SKLabelNodes and SKSpriteNode allocated with spriteNodeWithImage.
I have tried to use dealloc to monitor if scene got's deallocated correctly, and it appears to be so it seems it's not the source of the issue.
Browsing google pointed me to some other threads created on stackoverflow that
spriteNodeWithImage
textureWithImage
May cause
-Memory leaks
-weird error "CUICatalog: Invalid Request: requesting subtype without specifying idiom"
So i have tried to create UIImage imageNamed and then put in into texture and use in SKTexture, actually it has removed CUICatalog error (which anyway, seems like a stupid message which did not been removed by apple - can anyone confirm that ?)
But according to memory leaks this didn't help at all, and anyway anything in that scene is being created once on beginning so i have no idea why this memory keeps growing and growing like 0,5mb per sec.
Looking forward for any tips.
Best regards

Actually i have found the source of the problem.
It seems debugging physics makes huge memory leak
skView.showsPhysics = YES;
It's not a big problem since it happens while debugging only when showsPhysics=YES.
But good to know anyway.

Related

OpenGL app's framerate has detiorated following an upgrade from iOS7.1 to iOS8.1

The app uses OpenGL ES2 and the GLKit framework, and the render/update loop provided by GLKitViewController. It used to run at a steady 60 fps on my iPad2 with iOS7.1, but once I updated the iPad2 to iOS8.1, the exact same code now fluctuates between 56-59 FPS. (CPU utlitization, however, remains at 40-60% as before ).
Profiling reveals that the OpenGL drawing commands are using a much larger proportion of CPU time than they used to. The biggest change seems to be that calls to "GLKBaseEffect prepareToDraw" are taking much longer than they used to.
(The app uses a single GLKBaseEffect which is reconfigured at various points during the render loop, neccessitating a call to prepareToDraw each time. I realise it may be possible to optimize by having multiple instances of GLKBaseEffect, and that is something I was considering for later, however, the performance, as it was, was solid on iOS7.1)
I'm now examining theĀ OpenGL ES Analyzer trace in Instruments to determine the OpenGL calls generated by "GLKBaseEffect prepareToDraw", to see if anything seems unusual, and will update the post accordingly once I've managed to figure anything out.
I'd be very grateful for any guidance on how to progress at this point - why might calls to GLKBaseEffect prepareToDraw take longer on iOS8.1?
The cause of the problem was identified by Jim Hillhouse and confirmed by Frogblast on the Apple Dev Forums thread "OpenGL Performance Drops > 50% in iOS 8 GM": setting the text property of a UITextField (or UILabel, in my case) in a view which is a subview of GLKView is causing the GLKView superview to layout, which is then causing framebuffers to be deallocated and reallocated. This wasn't happening in iOS 7.
Jim Hillhouse's workaround was to place the subview inside a UIViewController, and embed that in GLKView. I've done the same, using a Container View to hold the view controller, and can confirm that it works.

Debugging a large memory leak in Instruments

I'm currently investigating what appears to be a large memory leak in my application. Using Instruments' Allocations template and the mark generation feature I can see that after a UIViewController that I present is released there is a growth of 35MB!
I know the UIViewControlller is released because I have a log message that is printed when dealloc is called.
One thing that really stands out in the report is the "VM: Allocation" item which shows 16MB of memory allocated. I have no idea what this is, also it's just two allocations using 8MB each, this seem incredibly high.
My UIViewController has a MKMapView, UITableView, various labels and a slideshow of UIImages.
The UIViewController is using a nib file and IBOutlets which are mostly all weak references, there are a few strong IBOutlet references where I add and remove view's at runtime that I need to keep a strong reference to. Though it's my understanding that these will be released by ARC anyway, just to be double sure I nil them out in dealloc.
Viewing the stack trace for the two VM: Allocations shows only internal calls and nothing that is related to my code. It says the responsible libraries are libGLVMPlugin.dylib and libCoreVMClient.dylib.
Interestingly if I remove my MKMapView from the nib file the growth shows after the UIViewController is released goes down dramatically.
Can anyone shed some light on this or give me any pointers?

UIImage being released but CGImage not being released

I appear to have a memory management issue when I create UIImage instances the CGImages are not being released.
I have a paging UIScrollView to scroll through a series of JPG images. Below is my entire class that is a page view in the paging scroll view.
The code is being run on the main thread. The code uses ARC. I have tried loading the images using imageWithContentsOfFile: (returns an autoreleased object) as well as initWithContentsOfFile:(returns a retained object). I have tried #autoreleasepool and using performSelectorOnMainThread to ensure that the code is being run on main thread as suggested in other posts.
When scrolling through the images memory usage just grows until the app gets terminated as illustrated in the screenshot from instruments. Note the high allocation to image io.
Screenshot showing virtual memory usage
In the following screenshot it can be seen that the GTGImageScrollerPageViews, UIImageViews and UIImages are being deallocated. Notice there are Transitory objects for these numbering in the high 300's. However the CGImages are not being released and the number of CGImages living is in the high 400's and 0 Transitory.
Screenshot showing allocations
EDIT: Previously I had been recycling and re-using GTGImageScrollerPageView instances in the ScrollView as is the common pattern for scrollviews like this. In order to simplify while trying to debug this problem I allow the entire GTGImageScrollerPageView to be deallocated after it has been displayed in the ScrollView. As you can see in the second image above, there are only 4 GTGImageScrollerPageView living and 377 transitory, there are also 388 UIImageViews and 389 UIIMages listed as transitory so it appears that the UIImageViews and UIImages are being deallocated fine.
If I manually release the CGImage with CGImageRelease (Commented out in the code below) the CGImages are released. I know that I should not do this because I do not own the CGImage but this is useful to verify that this is where the problem is occurring. The screenshots below show the same code tested in Instruments but with CGImageRelease uncommented.
Screenshot showing virtual memory usage with CGImageRelease used
Screenshot showing allocations with CGImageRelease used
In the profiling outputs where CGImageRelease is used, you can see that the correct number of CGImage objects are Living and Transitory and that memory does not grow unbounded. Furthermore the app does not crash during usage with CGImageRelease used.
If this were some system caching of CGImage then it should release the memory when a memory warning is raised, but it doesn't. Memory just continues to grow.
What here could be causing this unbounded growth in memory?
Here is the code for the page view
EDIT: In response to comments I have updated the code to simplify further thus eliminating distractions such as ivars and properties that are not needed to demonstrate the problem. The problem remains unchanged and the results are the same when profiling. I have also added in the NSLog which also outputs the thread. I do see the dealloc being called as expected on the GTGImageScrollerPageView and it is always thread #1 and the call to displayAspectThumbImage is always on thread #1.
I really dont believe that there is anything wrong with the code that is presented here and this is confirmed by the generous effort of Rob. Something else is causing this but all the code related to loading and displaying the image is here; there is no other code in effect here. The only other notable thing that I could think of raising is that the displayAspectThumbImage method is called from scrollViewDidScroll and scrollViewDidEndDecellerating methods of the scrollview delegate but the fact that the methods are called on the main thread should exclude autorelease issues due to being run on another thread.
I have checked and NSZombies is not enabled and there are no Zombies increasing my memory usage. Indeed when the CGImageRelease method is called the memory usage is pretty flat as can be seen in the screenshot above.
#implementation GTGImageScrollerPageView
- (void)dealloc {
NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSThread currentThread]);
}
- (void)displayAspectThumbImage:(NSString *)path {
NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSThread currentThread]);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds];
[self addSubview:imageView];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:path];
[imageView setImage:image];
//If uncommented CGImages are disposed correctly
//CGImageRelease([imageView.image CGImage]);
}
#end
Tested on:
iOS 6.1.4
iOS 5.0.1
Really sorry to be answering this question myself but thought it would be useful to share my experience.
It turned out to be a category on UIImage that was part of a third party library I was using. I wont name the library as I have tested with the latest version and the problem is not there so there is nothing to gain by naming the library.
It is particularly strange as the library was not being used anywhere near the code that was leaking. It was only being used in one place in the whole project, but any time I used a UIImage it seems that it was affecting the UIImage instance. The mere presence of this category in the project was enough. This came as a real surprise.
The way I solved this was to begin by simulating the scenario in a new project and found that the code was not leaking there. I then migrated the code a little at a time and when I moved the categories across the leak appeared.
Huge thanks to Rob for his generous efforts to help me with this and even though he did not provide the solution directly, talking to him was really helpful in solving the problem. Nice to know there are such cool people out there.
I did a simple infinite scroller using your code and after scrolling through nearly 100 images the memory usage was, as one would have expected, thoroughly uneventful:
Looking at your source, I would have recommended a few little things (e.g. I would have put aspectImageView into a private class extension rather than the .h, I assume you're setting pageIndex from the calling routine but I'd add it as a parameter of displayAspectThumbImage, I would have made aspectImageView a weak property and refactor the code accordingly (e.g. create image view, add it as subview, then set the weak imageview property to point to this object), etc.), but none of those have direct bearing on your issue here.
Bottom line, your problem does not rest in the code you've shared with us.
Try to use property instead of ivar.
#property (nonatomic, strong) UIImageView *aspectImageView;

Releasing memory in iOS 5 under arc

I know this question asked many times, but I have not yet found solution. My app goes between views in this order a->b->c->d->b. This means that from view "d" I don't always go back, and the needs to jump to view "b". The problem is that memory of views "c" and "d" is not release and after some loops (b->c->d->b->c....) the app crashes. It is very important the order of the operations. I have to mention that I navigate between views with modal segue. I have tried releasing memory in many ways:
Putting in DidRecieveMemoryWarning: _myProperty = nil;
Putting in ViewDidUnload: _myProperty = nil;
Changing all properties to weak.
Wrapping code with #autoreleasepool.
Nothing helped, the app crashes after awhile, how can release views and memory by "force"?
ARC was made for not releasing by force letting the OS handle all releases. You should use xcode instruments to find out how much memory your app is using. It sounds to me like you bloat your memory so it will be best for you to check how much memory is being used and what can you do to optimize it so allocation capacities will stay in an acceptable limits. (e.g. Loading 1000 images in a view where each image is 1Mb in size is a total waste and will probably cause such crash. This example is intentionally exaggerated so you'll get the idea)
Objective-C (primarily) uses a reference counting memory model. There's manual reference counting and Automatic Reference Counting (ARC).
How ARC Works
If you've ever worked with manual reference counting and run the clang static analyzer tool, you'll see that it does an amazing job of finding memory leaks. This is the idea behind ARC - if the analyzer can do such a good job of finding leaks, then why not let it perform memory management?
So, the analysis is done at compile time, and the resultant code is instrumented with retain and release calls. This is the foundation of ARC and its a great memory model, giving a good balance between performance and ease of use. Its especially useful in mobile computing, because, unlike garbage collection it won't require any additional CPU cycles or battery drain.
(NB: ARC also introduces weak references, which is a way of nulling out dangling pointers at runtime).
Using ARC is not quite as simple as garbage collection - you still need to know how the reference counting memory model works. The following problems can occur.
Retain Cycles
The main cause of a memory leak is a retain cycle. This is where object A has a reference to Object B, and Object B has a reference to Object A. For example an AirlineFlight contains a Passenger and the Passenger has an AirlineFlight -> memory leak.
This is very common in Cocoa. Another example is a ViewController owns a view, and the View has a delegate, which is the ViewController. Sound familiar?
To avoid the retain cycle, its necessary for one of the objects to not retain the other. The most common approach is to designate one as the parent, and the other as the child. The parent retains the child, but the child does not retain the parent. Example:
View Controller
#interface MyViewController
#property (nonatomic, strong) MyView* view
#end
View
#interface MyView
#property (nonatomic, assign) MyViewController* controller
#end
The retain-cycle is now broken and the memory leak will no longer occur.
Dangling Pointers
The above example no longer has a memory leak, but can lead to another problem - dangling pointers. The view controller might go away, while the view still has a reference to the controller. Any call to the controller will now cause a crash.
There's two ways to fix this:
Nil out the reference to the controller in the dealloc method. . . but probably just
Use a weak reference, as follows:
#property (nonatomic, weak) MyViewController* controller
iOS 5 and above (or OSX 10.7) have a little runtime utility that keeps track of dangling pointers and nils them out for you - these are called weak references.
Finding memory Leaks
There are several ways.
Use the clang static analyzer to detect retain cycles.
Use the Instruments tool
I like to put log statements in the dealloc method of my controllers and other key classes to ensure they being released.
Finding Dangling Pointers
Compile with the environment variable NS_ZOMBIES_ENABLED (or edit the Scheme in Xcode and click the checkbox, which will set this parameter for you).
Auto-release Pools
Another problem that can occur is too many objects being allocated within a run-loop. . To correct this you can create another auto release pool, within the main pool.
#autoreleasepool
{
}
(In your case, I don't think this is the problem).
I'v also come across this problem, but I was writing a cocoa app for OSX10.8, not iOS.
I found that the app memory usage will increase all the time when I do something like showing a new window then closing again and again. It seems like the window I see is a new one every time. 10MB->20MB->30MB...
Finally, I directly double-clicked the .app file, and checked the activity monitor again. The fact was that it really came to be normal. The app ran in release mode is the same situation. So I suppose ARC will not release memory immediately in debug mode if you run a app via Xcode Run.
Are you using heavy png images? I had this same problem a while ago and a height x width image uses height x width x 4 of RAM (since it is shared with GPU). Only my background wasted 120MB approx. If it is the case try to redimension your images.

Is it possible that NSZombie doesn't point out EXC_BAD_ACCESS with ARC?

i'm currently working on an ios project with some people, one of us decided to use ARC in a part of the app.
Unfotunatly, we are currently experiencing some crashes when coming back from background.
Here are the steps we follow to crash the application, we perform them with the ios-simulator:
start the application
get on a ViewController A (coded with ARC)
get on a ViewController B (not coded with ARC -to be honest i don't
know if it's relevant-)
put the application in background.
simulate a memory warning (thx to the simulator)
start again the application, we'll be on the ViewController B
go back on the Viewcontroller A
the application crashes pointing the main function with an
EXC_BAD_ACCESS
We did try to use NSZombieEnabled to YES, but when we do it, the application doesn't crash and keeps running perfectly, so we wonder if it might be possible that NSZombieEnabled doesn't work well with ARC?
if anyone could give me a quick and clear insight about ARC and NSZombieEnabled that would be apreciated, i think i know how all of it works, but apparently i must be missing something.
Thanks anyway for your help and time.
Better than using the NSZombieEnabled, you should Profile the project, and use the Zombie instrument. When you do the same thing it should stop and say "zombie messaged", where you can click an arrow to see the class that is a zombie, and where it was allocated/deallocated.
I don't think the crash has to do with ARC, instead in viewDidUnload you are deallocating something, and then not setting a reference to nil - when you come back it tries to use the invalid reference.
Probably you would be better off if everything used ARC as it really helps to cure issues like this (the bug is very likely in the non-ARC code).

Resources