I observed this behavior only on iOS 9; iOS 8 is working correctly.
I suspect this may be a bug in the SDK, and I opened the radar for Apple (22644754), but I find it so strange that I feel like I may miss a call or take a step to avoid a leak.
I noticed that every time CIContext.createCGImage is called, memory usage increases. The tricky part is that memory expansion occurs outside the application.
If you look at the “Memory Report” from Xcode, the memory increase will be visible in the “Other Processes” section.
Basically, I do to cause the problem: (I simplified the code for the strictly parts needed to reproduce the leak):
First I create a CIContext supported by EAGLContext:
let glContext = EAGLContext(API: .OpenGLES2)! let ciContext = CIContext(EAGLContext: glContext, options: [kCIContextOutputColorSpace : NSNull()])
Then I create an image using the following:
let input = CIImage(image: UIImage(named: "DummyImage")!)! ciContext.createCGImage(input, fromRect: input.extent)
DummyImage is just a sample image file. The leak is directly related to the size of this image, so it’s better to use a larger one to make the problem more noticeable.
As you can see, I do not use any CIFilters (using them leads to the same result), and I do not collect the resulting image (even if I captured it, I could not use CGImageRelease, since the objects are automatically managed).
If the visualization code is executed enough times, the memory will grow so much that the running applications will be killed.
One interesting observation is that destroying a CIContext does not matter, but destroying an EAGLContext returns the returned memory. This makes me think the leak is on the OpenGL side.
Am I missing something in my code that might cause a leak? Is there any call I can make to free the memory received by EAGLContext? (Re-creating it all the time is not an option, as it is an expensive operation).
I created a simple project to reproduce the problem. You can find it at:
https://www.dropbox.com/s/zm19u8rmujv6jet/EAGLContextLeakDemo.zip?dl=0
Steps to play:
- Open and run the connected project on the device.
- Check out the Memory screen on Xcode. Growth will be observed in the Other Processes section of the Use Comparison pie chart.
- The application contains three buttons. Each of them will execute the createCGImage command a certain number of times (shown on the button labels).
- Pressing any of the buttons will increase memory usage in "other processes". This may be more noticeable after several calls to createCGImage.
- Pressing the 100 Renders buttons will more clearly show the effect.
- If there is an excessive increase in memory, the application will crash.