KmlLayer memory leak

2936
3
Jump to solution
06-03-2013 03:48 AM
Labels (1)
BjørnarSundsbø
Occasional Contributor
Hi,

I'm currently using the 2.3 version of the library as we haven't been able to update yet (and 2.4 has a bug we can't live with). I reference a few KML Layers that has a refresh interval of 5 minutes. We experience a memory leak that eventually crashes the application with OutOfMemoryException. Tuning the KML file to refresh every 10 seconds will make the application eat memory quite rapidly.

I have read through the release notes for later releases, but have not found any resolved issue related to this. Is this memory leak still an issue? If it is, this is a bug report 🙂

I will try to build the Toolkit from http://esrisilverlight.codeplex.com/ with my current version to see if it solves anything, as I assume this is the toolkit that is still being used by version 10.1.1.

EDIT:
After removing all the classes that doesn't have to do with KML, and some other modifications because of incompatible version of ESRI.ArcGIS.Clients, I have confirmed that the memory leak is still present in the latest version (January, 2013) of the Toolkit. I do not currently have the opportunity to research it and provide a solution. Is this something the ESRI team will look into in the near future?
0 Kudos
1 Solution

Accepted Solutions
BjørnarSundsbø
Occasional Contributor
I have been able to identify and resolve the leak.

In KmlLayer, introduce the following method
        private void ClearLayers()         {             if (ChildLayers.Any())             {                 foreach (Layer child in ChildLayers.ToList())                 {                     // Fixes memory leak on refresh. Remove individual layers so each layer will be teared down properly by GroupLayer.                      // ChildLayers.Clear() will cause a reset event, which will not contain NewItems/OldItems so they can be unsubscribed                     ChildLayers.Remove(child);                 }             }         }


Replace every call to ChildLayers.Clear() with a call to this method.

As mentioned, I am running version 2.3 of the WPF library, so this is something that may have been fixed in ArcGIS Runtime for WPF 10.x.

View solution in original post

0 Kudos
3 Replies
MichaelBranscomb
Esri Frequent Contributor
Hi,

Are you able to share details of the KML Layers that you are experiencing problems with?

Cheers

Mike
0 Kudos
BjørnarSundsbø
Occasional Contributor
Attached example KML source. Local paths are not supported. Exposing this on a web site should take care of it. You may have to update Icon href in TrafficInformation.kml and link href in Refresh

Add KmlLayer reference to TrafficInformationRefresh.kml

Findings so far:
It appears that there may be several causes for the leak, and I may have identified some. Using ANTS memory profiler, I locate the leak to an impressive number of WeakReferences. Tracing their path, they end up in a few possible hotspots. KmlPlaceMakerSymbol and KmlGraphicsLayer. Looking at the kind of connection, it is PropertyChanged event still having a reference to the map.

When the KML is parsed, new instances of KmlLayer and KmlGraphicsLayer are created. They subscribe to PropertyChanged and Map.PropertyChanged at some point in their construction and initialization. When the layer is refreshed, ChildLayers.Clear() is called from the main layer, but these PropertyChanged events are never unsubscribed. Both parentLayer (which is the KmlLayer I add to the map), and Map lives on throughout the whole lifetime of the application.

I introduced IDisposable to both KmlLayer and KmlGraphicsLayer. Inside of KmlLayer, in every location ChildLayers is called, I instead call a new method named ClearLayers() which will iterate the children and call Dispose before clearing LayerCollection.

KmlLayer.Dispose
- Unsubscribe Map.PropertyChanged
- Iterate and dispose ChildLayers

KmlGraphicsLayer.Dispose
- OnMapChanged(Map, null)

Profiling after making these changes, I still have a memory leak (and memory fragmentation). Now it is KmlPlaceMakerSymbol that is the root of evil. I have not identified what the GC root is now, but it an Object[] related to DataBindings (1 instance).

Since my version of ESRI.ArcGIS.Client is 2.3, I do not know what other changes may have been done to the classes in this assembly that may have fixed this leak in later releases. I am building a stripped down version of Toolkit.DataSources to contain only KmlLayer and related classes.

LayerCollection should have cleaned up Map.PropertyChanged when cleared (or individual items are removed). Or layers themselves should have unsubscribe implemented when they are removed from the map.

This memory leak may also be in effect for other layers as well, but I'm guessing they are not recreated as often as KML services with refresh, so in effect it is probably not something we notice.

In the attached screenshot, there is a KmlGraphicsLayer to the right in the path. Of course, there are more paths that hold these references with a high count.
0 Kudos
BjørnarSundsbø
Occasional Contributor
I have been able to identify and resolve the leak.

In KmlLayer, introduce the following method
        private void ClearLayers()         {             if (ChildLayers.Any())             {                 foreach (Layer child in ChildLayers.ToList())                 {                     // Fixes memory leak on refresh. Remove individual layers so each layer will be teared down properly by GroupLayer.                      // ChildLayers.Clear() will cause a reset event, which will not contain NewItems/OldItems so they can be unsubscribed                     ChildLayers.Remove(child);                 }             }         }


Replace every call to ChildLayers.Clear() with a call to this method.

As mentioned, I am running version 2.3 of the WPF library, so this is something that may have been fixed in ArcGIS Runtime for WPF 10.x.
0 Kudos