brian.mullins

Runtime 10.1.1: Memory Leak in CoordinateConversion class

Discussion created by brian.mullins on Jun 20, 2013
Latest reply on Jun 21, 2013 by MBranscomb-esristaff
I am using version 10.1.1 of the ArcGIS Runtime SDK for WPF.  A class that I think was just added in 10.1.1 is the CoordinateConversion class which makes it easier to convert to/from different spatial references.  Recently, when using this class for our coordinate projections we noticed our application started crashing with out of memory exceptions.  After writing a test program, I was able to verify that the CoordinateConversion class is leaking memory.

There are 3 cases that I tested for:
1.  Use CoordinateConversion class to convert from spatial reference 4326 to 102100 (WGS84 to WebMercator).
2.  Use CoordinateConversion class to convert from spatial reference 4326 to 4326 (basically a no-op).
3.  Use the WebMercator class to convert from spatial reference 4326 to 102100.

I found that only the first case causes it to leak memory.  And from examining it with a memory profiler there appeared to be a very large amount of strings and character arrays that were leaking.

Here is my test program:
using System;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Projection;

namespace CoordinateProjectorTest
{
  internal static class Program
  {
    private static readonly Random Random = new Random();

    private static void Main( string[] args )
    {
      var isConvertingToWebMercator = Convert.ToBoolean( args[0] );
      var useCoordinateConversion = Convert.ToBoolean( args[1] );
      var spatialReference = new SpatialReference( isConvertingToWebMercator ? 102100 : 4326 );
      var webMercator = new WebMercator();

      if ( useCoordinateConversion )
        for ( var i = 0; i < 1000000; i++ )
          Console.WriteLine( "{0}: {1}", i, CreateRandomCoordinate( spatialReference ) );
      else
        for ( var i = 0; i < 1000000; i++ )
          Console.WriteLine( "{0}: {1}", i, webMercator.FromGeographic( CreateRandomMapPoint() ) );

      Console.ReadKey();
    }

    private static MapPoint CreateRandomCoordinate( SpatialReference spatialReference )
    {
      var latSign = Random.Next( 0, 2 ) == 0 ? "N" : "S";
      var lonSign = Random.Next( 0, 2 ) == 0 ? "E" : "W";
      var coord = String.Format( "{0}{1} {2}{3}", CreateRandomDouble( 90.0 ), latSign, CreateRandomDouble( 180.0 ), lonSign );
      return CoordinateConversion.DecimalDegreesToMapPoint( coord, spatialReference );
    }

    private static MapPoint CreateRandomMapPoint()
    {
      return new MapPoint( CreateRandomDouble( 180.0 ), CreateRandomDouble( 90.0 ), new SpatialReference( 4326 ) );
    }

    private static double CreateRandomDouble( double factor )
    {
      return Random.NextDouble() * factor;
    }
  }
}


Just copy this code into an x86 console application and watch the memory usage.  Note: if you compile this into a x64 (or AnyCPU on a 64-bit computer) build platform target it won't actually run out of memory but memory usage will be very high.  The input parameters to make it crash are "true true" on the command line when running this program.

Outcomes