Hey Rolf,
Thanks again for the reply - this is very helpful. Yes, I am profiling on an actual device, and no, I'm not creating any threads in this code. I wonder if the UITableView that's in use is creating these threads. Thanks for the tip about looking at the full graph instead of the diff. I was thinking the diff would be most important, but I've changed my strategy. This time I loaded my menu over and over until 80%+ of the app's memory is filled with leaked objects, that way I can look at the full dump instead of the diff and still be mostly looking at leaked objects. http://i.imgur.com/cy2C9.png Am I correct in assuming that the correct way to use the mono profiler is to expand the trees out to the bottom, and once you reach something that doesn't expand, that tells you what's preventing the GC from collecting everything above it? When I do this, ultimately all of these strings expand down to one of my UIView subclasses and then an <Other Root> below it - I expanded every node to be sure. What does <Other Root> mean in this context? Could this mean that something is keeping a reference around to my UIViews even after everything that used them has been popped from the navigation controller? Is there any way to see what this is or debug this further? I forgot to mention my MonoTouch version: 6.0.4. I have the SGen box checked, but not the reference counting extension box (though I see the same behavior in all three configurations). Thanks! From: Rolf Bjarne Kvinge [mailto:[email protected]] Sent: Tuesday, October 30, 2012 2:41 PM To: Randy Ficker Cc: [email protected] Subject: Re: [MonoTouch] Understanding the memory profiler Hi, On Tue, Oct 30, 2012 at 10:03 PM, Randy Ficker <[email protected]> wrote: Hey Rolf, Thanks for the reply! I've gotten more familiar with Instruments now, and I've started taking several heapshots as you advised. When looking at the 1000+ objects that are making up the 100kb+ memory leak, it essentially just looks like everything my app is allocating. So I believe the real question I need to answer is "Why isn't Mono collecting these?" This is where I turn to the mono profiler and get really confused. It hardly shows anything, and most of what it does show isn't my code (it's all System.* and MonoTouch.* types). This is the view with Inversed References: http://i.imgur.com/Z0MuD.png If my goal is to figure out why the Mono GC isn't collecting something, I assume Instruments won't tell me that, correct? Will the mono profiler tell me that? Is there any other way to find out? If you're not doing it, you should be profiling on device - device builds have been optimized for execution speed and lower memory consumption, while simulator builds have been optimized for fast project builds (this is so you can quicker debug your app after making a change). You're right about Instruments, it will not tell you why Mono's GC isn't freeing a managed object, that's where the Mono Profiler will help you. >From your screenshot I find a couple of things: * Are you creating threads for every heapshot iteration? The string instances you've expanded are references by a System.Threading.Thread object through its Current[UI]Culture - and those will stay alive as long as the thread stays alive (and the Thread objects show up at the bottom too). * Many objects can't be expanded in your screenshot - this is because their parent isn't included in the diff between the two heapshots. You might want to untick the 3 after figuring out which type you're interested in to see the full tree of objects referencing it. * In general most objects will be framework types (System.* or MonoTouch.*) - but you will usually find your own objects at the top of the tree keeping all those framework objects alive (there are a few exceptions of course, such as the Thread object, which is automatically kept alive until the corresponding thread exits without you actually having to keep a reference to it). Rolf Rolf Thanks! From: Rolf Bjarne Kvinge [mailto:[email protected]] Sent: Tuesday, October 30, 2012 10:55 AM To: Randy Ficker Cc: [email protected] Subject: Re: [MonoTouch] Understanding the memory profiler Hi, On Mon, Oct 29, 2012 at 9:07 AM, Randy Ficker <[email protected]> wrote: I believe my MonoTouch app is leaking memory, and I've been struggling at figuring out why. By using Instruments I can see the allocated memory grow and grow over the life of the app, eventually causing the app to die after 10 minutes or so of general use on my 3GS. To help isolate the problem, I first picked a specific action in my app I can easily repeat - just opening a menu and closing it again, which shouldn't leave any garbage behind as the code is well-contained. Using Instruments, I can see that just opening and closing this menu adds about 90KB of allocations each time. If I open and close it 11 times, I've added a megabyte to my app's memory use. I first tried enabling SGen and then the reference counting extension. Neither configuration changed the memory allocated. I tried commenting out parts of the menu that I thought might be leaking (images, custom-draw views, etc.). Doing this did reduce the memory leakage, but even if I comment out all of the functionality (to the point where my menu came up blank) it was still leaking 40KB each time. So I still feel I'm missing something fundamental. I was concerned that the garbage collector might just not be running, flawing my test results. I added a call to GC.Collect() but that didn't change anything. I also tried doing it 50 times in a row, leaking over 4 megs of memory, to see if the GC would eventually collect it all. It never did. Throughout this, I've been trying to understand the mono memory profiler. Following the instructions, I take a shot, open and close my app's menu, and take another shot, then diff them, and I see this: http://i.imgur.com/N4Ngb.png. Checking "Roots only" doesn't change anything (the three new columns are empty). Instruments->Leaks shows this: http://i.imgur.com/hbJQ1.png First: you should do more than 1 heapshot, do several until the heap growth settles around a ~fixed amount, otherwise there will be some noise (iOS caches some this heavily) in the output (this is true for the Mono profiler too). Then you can start examining the result - your screenshot shows various objects which haven't been freed. You can see the stack trace for where each of these objects were created by expanding it and selecting a specific instance, then showing the extended detail view (in the toolbar, there are three buttons above the label "View" - click on the right-most button). For comparison, I also ran the profiler against my code with virtually all of my code commented out (it was just bringing up a blank menu). Memory leak is about 40KB in this scenario: http://i.imgur.com/eIlK7.png I'm very confused by these results. My questions are: 1. What is <Other Root> and why does it have thousands of instances that total 0 memory? This appears to be the common factor in both of them. Other Roots are usually GCHandles - you can normally just ignore these roots, they are very rarely the cause for any problems. 2. In the first one, it says 20KB of strings leaked. How can I tell where these are coming from or why they aren't being collected? 3. What uses System.WeakReference and why would it be leaking? For both 2. and 3. you should check the "Inverse References" checkbox, and then expand the treeview for the objects you want to examine - this will allow you to see what types reference the topmost type. 4. The mono profiler only seems to account for a small part of the total memory being leaked. Is there anything else I can try? The mono profiler only knows about managed memory, not everything allocated in the app (only Instruments have a global knowledge of memory in the app, but it can be tricky to get the interesting information out of Instruments). 5. What else can I do to try and figure out why my app is continually growing in memory? I feel like I'm missing something fundamental here. I'd appreciate any advice anyone can offer! _______________________________________________ MonoTouch mailing list [email protected] http://lists.ximian.com/mailman/listinfo/monotouch
_______________________________________________ MonoTouch mailing list [email protected] http://lists.ximian.com/mailman/listinfo/monotouch
