I have only observed this behaviour on iOS 9; iOS 8 works correctly.
I suspect this might be a bug on the SDK, and I have opened a radar to Apple (22644754), but I find it so strange, that I get the feeling that I might be missing a call or a step to avoid the leak.
What I have observed is that every time CIContext.createCGImage is called, there is a memory usage increase. The tricky part is that the memory increase occurs outside of the app.
If you look at the "Memory Report" from Xcode, the memory increase is visible on the "Other Processes" section.
Basically, what I do to cause the problem is the following (I have simplified the code to strictly the parts necessary to reproduce the leak):
First I create a CIContext backed by a EAGLContext:
let glContext = EAGLContext(API: .OpenGLES2)!
let ciContext = CIContext(EAGLContext: glContext, options: [kCIContextOutputColorSpace : NSNull()])
Then, I render 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 associated to the size of this image, so it is best to use a big one in order to make the problem more noticeable.
As you can see, I'm not using any CIFilters (using them causes the same result), and I'm not capturing the resulting image (Even if I captured it, I couldn't use CGImageRelease as the objects are automatically managed).
If the render code is executed enough times, the memory will grow so much that the running apps will get killed.
One interesting observation is that destroying the CIContext does not make a difference, but destroying the EAGLContext does return the taken memory. That makes me think that the leak is happening on the OpenGL side.
Am I missing anything in my code that can cause the leak? Is there any call I can make to free up the memory taken by the EAGLContext? (Recreating it all the time is not an option as it is a costly operation).
I have created a simple project to reproduce the issue. You can find it at:
https://www.dropbox.com/s/zm19u8rmujv6jet/EAGLContextLeakDemo.zip?dl=0
The steps to reproduce are:
- Open and run the attached project on a Device.
- Observe the "Memory Report" screen on Xcode. The growth will be seen on the "Other Processes" part of the "Usage Comparison" pie chart.
- The app presents three buttons. Each of them will execute the createCGImage command a certain number of times (shown on the button labels).
- Tapping on any of the buttons will result on a memory usage increase of the "Other Processes". This might be more noticeable after performing several createCGImage calls.
- Tapping on the 100 Renders buttons will show more clearly the effect.
- When the memory growth is excessive, the App will crash.
bytesPerPixel = 8
? Isn'tkCIFormatRGBA8
a 4 byte per pixel format? – Steakhouse