Hi Guys,
We have an application built with the ArcGIS Runtime SDK for .net that's been around for several years now with relatively few changes. We have fixed some bugs in that time and this has required us to periodically upgrade to the latest version of the SDK. Our most recent release is in fact built against version 100.9 of your SDK.
Chart items from our application can be added to the map and one of the things we implemented a long time ago is visual clustering on the map surface. This occurs both when the user zooms in or out and when they toggle our clustering feature on and off.
Each graphic on the map represents one of our own chart items and the graphics therefore potentially have unique images, unique text labels and a triangular symbol that points to the relevant geographic location.
The way this was implemented was with graphics that each have a unique composite symbol and are dynamically added to, and removed from, a single graphics overlay.
The clustering algorithm dynamically calculates the clusters and assigns these graphics to the appropriate cluster, each cluster being represented by a new graphic with its own composite symbol. These cluster symbols are essentially just a circle with a text label showing the count of graphics in the cluster but they also show selection state including a special state when only some of the cluster contents are selected on our chart.
To summarize, at any point in time the graphics overlay will contain composite symbols representing individual chart items, clusters or both.
The graphics and symbols for the clusters are dynamically created but the graphics and symbols for the individual chart items are created once and cached by us.
Each clustering operation re-groups these cached graphics removing the overhead of their creation.
What we have noticed recently (initially via our application crashing) is that there appears to be a memory leak in your unmanaged code. The problem occurs in many scenarios but the easiest way for us to reproduce it is to add say 50,000 chart items to the map and repeatedly zoom in and out or, even just repeatedly toggle clustering on and off. Both of these operations remove and re-add existing graphics to the overlay which eventually causes the applicaition to crash with an out of memory exception.
There is obviously always going to be a finite number of graphics you can add before running out of memory and our application is currently 32 bit so we are constrained by the 4GB limit. We are nowhere near this limit however when the graphics are initially all created and added to the overlay.
I have created and attached a simple application that demonstrates this problem. The demo application initially creates and caches 50,000 graphics with a similar symbol to those in use by our main application. It then goes on to repeatedly add and remove these graphics (on the UI thread) to the graphics overlay in the handler for a System.Windows.Forms.Timer.
I have profiled both our application and this little demo app and in both cases the memory footprint continues to grow until it eventually crashes. This occurs much quicker in our application as there is obviously less memory available in that context.
Analysis of the profiling results show that the .net memory seems to be pretty well behaved but the unmanaged memory just continually grows with each add/remove cycle.
The demo app is pretty simple but I've tried to make it comparable to our real application and for that reason the map control is inside an ElementHost. I don't think that really makes any difference however as at some point I did try it in a pure WPF application with the same results. It might seem a little odd in places and there are definitely better ways to write this demo app in isolation, but I've just lifted code and adapted it as little as possible to demonstrate the issue. Again, the intention was to keep it as close to the real code as possible.
To build it you will just need to add the Esri.ArcGISRuntime.WPF v100.9.0 package in the NuGet package manager. The graphics are all created on the first timer tick so after the map initially displays there will be sizeable delay whilst that happens. The graphics are subsequently just added and removed on alternate ticks so you can take a memory snapshot when they first appear and then another a few iterations later, or just watch the memory climb in the visual Studio Diagnostic Tools Window. I've actually profiled it in a few different tools to come to my conclusions.
I would appreciate someone taking a look and either confirming my findings or letting me know if there's some other issue I've overlooked.
Regards,
Kevin