I have an app with several views. One of these views is always visible. All views are cached by the view factory, so I have only one instance of each view. The user can navigate between views. During such navigations I take a target view from the factory and set it as a page content. Most views are very trivial; others (are also trivial, but) contain lists with up to 100-120 items (usually ~20-30). When I switch between views several times (let say 13, but whatever) the app crashes with OutOfMemoryError and with the following stack trace:
Java.Lang.OutOfMemoryError:
at at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <IL 0x00011, 0x00078>
at Android.Runtime.JNIEnv.CallStaticObjectMethod (intptr,intptr,Android.Runtime.JValue*) [0x00064] in /Users/builder/data/lanes/1879/5f55a9ef/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:1301
at Android.Graphics.Bitmap.CreateBitmap (int,int,Android.Graphics.Bitmap/Config) [0x0006c] in /Users/builder/data/lanes/1879/5f55a9ef/source/monodroid/src/Mono.Android/platforms/android-21/src/generated/Android.Graphics.Bitmap.cs:715
at at Xamarin.Forms.Platform.Android.ButtonDrawable.CreateBitmap (bool,int,int) <IL 0x00007, 0x0008f>
at at Xamarin.Forms.Platform.Android.ButtonDrawable.Draw (Android.Graphics.Canvas) <IL 0x00056, 0x0026b>
at Android.Graphics.Drawables.Drawable.n_Draw_Landroid_graphics_Canvas_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/1879/5f55a9ef/source/monodroid/src/Mono.Android/platforms/android-21/src/generated/Android.Graphics.Drawables.Drawable.cs:1382
at at (wrapper dynamic-method) object.c46054a1-7b98-454c-9938-fe7e0c262669 (intptr,intptr,intptr) <IL 0x00017, 0x00043>
at --- End of managed exception stack trace ---
at java.lang.OutOfMemoryError
at at android.graphics.Bitmap.nativeCreate(Native Method)
at at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
at at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
at at android.graphics.Bitmap.createBitmap(Bitmap.java:670)
at at md5530bd51e982e6e7b340b73e88efe666e.ButtonDrawable.n_draw(Native Method)
at at md5530bd51e982e6e7b340b73e88efe666e.ButtonDrawable.draw(ButtonDrawable.java:49)
at at android.view.View.draw(View.java:14838)
at at android.view.View.getDisplayList(View.java:13744)
at at android.view.View.getDisplayList(View.java:13786)
at at android.view.View.draw(View.java:14563)
at at android.view.ViewGroup.drawChild(ViewGroup.java:3316)
at at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3153)
....
at at android.view.View.draw(View.java:14563)
at at android.view.ViewGroup.drawChild(ViewGroup.java:3316)
at at android.widget.ListView.drawChild(ListView.java:3390)
at at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3153)
at at android.widget.AbsListView.dispatchDraw(AbsListView.java:2810)
at at android.widget.ListView.dispatchDraw(ListView.java:3385)
at at android.view.View.draw(View.java:14856)
at at android.widget.AbsListView.draw(AbsListView.java:5051)
at at android.view.View.getDisplayList(View.java:13744)
at at android.view.View.getDisplayList(View.java:13786)
at at android.view.View.draw(View.java:14563)
at at android.view.ViewGroup.drawChild(ViewGroup.java:3316)
at at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3160)
at at android.view.View.draw(View.java:14856)
...
at at android.widget.FrameLayout.draw(FrameLayout.java:467)
at at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2621)
at at android.view.View.getDisplayList(View.java:13744)
at at android.view.View.getDisplayList(View.java:13786)
at at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1411)
at at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1359)
at at android.view.ViewRootImpl.draw(ViewRootImpl.java:2672)
at at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2538)
at at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2154)
at at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1249)
at at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6364)
at at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
at at android.view.Choreographer.doCallbacks(Choreographer.java:591)
at at android.view.Choreographer.doFrame(Choreographer.java:561)
at at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
at at android.os.Handler.handleCallback(Handler.java:730)
at at android.os.Handler.dispatchMessage(Handler.java:92)
at at android.os.Looper.loop(Looper.java:176)
at at android.app.ActivityThread.main(ActivityThread.java:5419)
at at java.lang.reflect.Method.invokeNative(Native Method)
at at java.lang.reflect.Method.invoke(Method.java:525)
at at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at at dalvik.system.NativeStart.main(Native Method)
First of all, I have no guess, where I can have a memleak. I would like to profile, but the profiler does not work for me - when I start profiling the build happens, deployment goes well, profiler starts and suggest to select what I want to profile (allocations, timings, or all together), but then.... nothing. The app just does not start...
Second. I share business logic (actually everything excepting views and some NFC and USB-Host related stuff) with desktop WPF-based app. I profile WPF app and I see no memleaks there.
Third. I always get the same stack trace, which makes me think that it somehow related to drawing engine. What actually Xamarin.Forms.Platform.Android.ButtonDrawable.CreateBitmap can do? I have buttons on the view (where crash happens), but all of these are transparent and without any text (I make command bindings for list items in such way, all my items have custom drawing). So why bitmaps creating?
Fourth. I use two custom fonts very actively - actually every icon or text is drawn using the custom font. Can it somehow affect on memory usage?
I understand, I've gave not much info about the app, but an app itself is quite big, and I have no idea what can be useful for further investigation. I'll provide any details, if needed.
Update
I just removed my invisible buttons from the list and can see the difference. I'm not able to crash the app anymore, which is good. However, I can see that GC takes more and more time every time it starts.
It is what I can see during switch from "light" view to "heavy":
[Mono] GC_OLD_BRIDGE num-objects 37 num_hash_entries 206088 sccs size 39800 init 0.00ms df1 451.67ms sort 176.32ms dfs2 128.80ms setup-cb 23.45ms free-data 181.87ms links 402547/402547/437282/11 dfs passes 608672/442347
[Mono] GC_MINOR: (Nursery full) pause 465.29ms, total 465.37ms, bridge 753.02ms promoted 48K major 19904K los 932K
And several GC happens while I scroll list from top to bottom:
[Mono] GC_OLD_BRIDGE num-objects 40 num_hash_entries 207056 sccs size 39767 init 0.00ms df1 498.18ms sort 219.27ms dfs2 143.32ms setup-cb 34.37ms free-data 232.57ms links 404545/404545/278080/7 dfs passes 611641/444312
[Mono] GC_MINOR: (Nursery full) pause 517.30ms, total 517.39ms, bridge 847.48ms promoted 1216K major 21120K los 932K
[Mono] GC_OLD_BRIDGE num-objects 4 num_hash_entries 4 sccs size 4 init 0.00ms df1 0.37ms sort 0.02ms dfs2 0.09ms setup-cb 0.00ms free-data 0.03ms links 0/0/0/0 dfs passes 8/4
[Mono] GC_MINOR: (Nursery full) pause 12.04ms, total 12.27ms, bridge 201.26ms promoted 176K major 21296K los 1060K
[Mono] GC_OLD_BRIDGE num-objects 4 num_hash_entries 4 sccs size 4 init 0.00ms df1 0.37ms sort 0.01ms dfs2 0.09ms setup-cb 0.01ms free-data 0.03ms links 0/0/0/0 dfs passes 8/4
[Mono] GC_MINOR: (Nursery full) pause 12.29ms, total 12.61ms, bridge 197.53ms promoted 240K major 21536K los 1188K
[Mono] GC_OLD_BRIDGE num-objects 2 num_hash_entries 2 sccs size 2 init 0.00ms df1 0.25ms sort 0.00ms dfs2 0.03ms setup-cb 0.00ms free-data 0.05ms links 0/0/0/0 dfs passes 4/2
[Mono] GC_MINOR: (Nursery full) pause 13.00ms, total 13.22ms, bridge 228.32ms promoted 304K major 21840K los 1253K
[Mono] GC_OLD_BRIDGE num-objects 4 num_hash_entries 4 sccs size 4 init 0.00ms df1 0.10ms sort 0.01ms dfs2 0.07ms setup-cb 0.01ms free-data 0.04ms links 0/0/0/0 dfs passes 8/4
[Mono] GC_MINOR: (Nursery full) pause 8.67ms, total 8.76ms, bridge 248.72ms promoted 256K major 22096K los 1381K
[Choreographer] Skipped 32 frames! The application may be doing too much work on its main thread.
[Mono] GC_OLD_BRIDGE num-objects 7 num_hash_entries 207346 sccs size 39934 init 0.00ms df1 437.00ms sort 193.84ms dfs2 90.03ms setup-cb 23.20ms free-data 171.41ms links 404973/404973/39927/1 dfs passes 612326/444907
[Mono] GC_MINOR: (Nursery full) pause 454.99ms, total 455.17ms, bridge 670.38ms promoted 1968K major 24064K los 1381K
[Choreographer] Skipped 71 frames! The application may be doing too much work on its main thread.
[Mono] GC_OLD_BRIDGE num-objects 3 num_hash_entries 207888 sccs size 39951 init 0.00ms df1 486.86ms sort 171.43ms dfs2 92.86ms setup-cb 23.51ms free-data 165.43ms links 406088/406088/79893/2 dfs passes 613979/446039
[Mono] GC_MINOR: (Nursery full) pause 511.48ms, total 511.60ms, bridge 649.23ms promoted 2304K major 26368K los 1381K
[Choreographer] Skipped 75 frames! The application may be doing too much work on its main thread.