I am building an iPad app that is essentially a presentation viewer. In simple terms you have a main menu which links off to different presentations. You view a presentation and when you are finished with it you close it and return to the main menu where you can select another presentation.
Each presentation contains quite a lot of large images, text, and videos etc so memory management is really important.
Each presentation also contains a slider element which is used to flick through a series of images. For the purpose of debugging I have removed the event listener from the slider so that it doesn't do anything at all - I literally create a new slider and add it to the window (more on this later).
I am experiencing crashes when using the app for a while to open and close presentations. When profiling the app to investigate this I have noticed some odd behaviour that I can't get my head around.
This image shows the typical memory usage when using the app:
![Memory Profile Graph]("http://imgur.com/BcjFS" "Memory Profile")
I have highlighted the key events:
- Open 1: the first presentation is opened, memory increases as expected
- Close 1: the first presentation is closed - no memory gets released here
- Open 2: another presentation is opened - memory increases as the new presentation is loaded in, but then drops as the old presentation is garbage collected
- Close 2: the second presentation is closed
- Open 3: another presentation is opened - same behaviour as last time
- After opening the third presentation I move the slider slightly
- Close 3: presentation is closed - same behaviour as last time
- Open 4: another presentation is opened - Note: old presentation is not garbage collected so overall memory increases
- Close 4: fourth presentation is closed - same behaviour as before
- Open 5: another presentation is opened - same behaviour as before
So to summarize, there are 2 issues here: 1. Each presentation is not cleared from memory until a new one is opened. Even if you wait for ages, interact with other elements or create new element, the first presentation is not cleared from memory until a second one is opened. 2. When interacting with the slider (which doesn't do anything) the presentation which contains it is never released from memory.
I have used the example of a slider here, but it happens for some other elements too, such as table rows. In each case I have stripped it back to the bare bones where I simply create the element and add it to the window. The results are the same every time - when I open and close presentations without changing the slider, the presentation is always cleared from memory next time I open one. However if I move the slider, the presentation stays in memory and is never garbage collected.
This behaviour is exactly the same every time. I must have tested it over a hundred times by now! The end result is that unless you don't interact with certain element in the presentations, over time the memory will build up and the app will crash. Due to the size of the content in the presentations it doesn't take too many opens and closes for this to happen (around about 10 depending on device).
I am using Ti 1.8.2 (although I have also tried it in 2.0 and 2.1.3 with the same resutls). I am also using TiAir and Redux by Dawson Toth although I have used these in the past with no problems. I am also using several techniques to handle memory management:
a memory pool technique as described here: http://developer.appcelerator.com/question/116867/this-is-a-solution-to-your-memory-woes
I have meticulously gone through my code ensuring there are no references left lying around after they are finished with (following advice in this video: http://vimeo.com/29804284)
there are no global variables used for the presentation viewer
So, to finally get round to asking my questions:
Why is each presentation not garbage collected until a new one is opened?
Why would interacting with an element such as a slider cause the presentation not to get garbage collected, even though the slider has no event?
Any help or advice would be really appreciated! I've been banging my head against the wall for over a week now! :)
Here are the things I would try, based on experience. I'm not sure how many of these tricks are still relevant, but it seems you have the skill & knowledge to test them out:
- Manually clean up your images on destroy.
myImage = undefined; // null will continue to use memory
- Instead of using imageviews, try using a view with a backgroundImage
- If you have any non-UI objects that are taking up memory, be sure to release them manually using the same "undefined" technique above.
I can't tell you what's wrong in this particular case because you haven't provide any code - it might be your fault, but also it could be platform issue.
In any case - you should never worry about memory management! I've built huge app that has 800 UI element in just one tab (and in that tab, new windows can be opened with new UI elements) and I don't have a single line that sets some variable to "null". Setting to "null" is almost never a solution, you firstly need to find out what's causing memory leak problems. Try to use "Instruments" to track what UI elements don't get released: http://docs.appcelerator.com/titanium/2.1/index.html#!/guide/Managing_Memory_and_Finding_Leaks-section-29004941_ManagingMemoryandFindingLeaks-MonitoringallocationsoniOS and try to post some code here that shows the issue.
You can also read my blog post about memory leaks in Titanium: http://zenborgium.blogspot.com/2012/04/ultimate-answer-to-titanium-memory.html
Think you can help? Login to answer this question!