ArcGIS Pro layer add performance issue

737
1
03-09-2017 11:24 AM
Jean-PaulLavoie1
New Contributor

I am having a performance issue with ArcGIS Pro (1.4).  I need to create a map programmatically that contains about 50 layers.

The tests were performed under Windows 10 Pro via VMware running on a Macbook Pro with an i7 @ 3.10 ghz.  The tests were repeated when the VM was set up with 4gb, 8gb, and 12gb allocated ram with no appreciable difference.  The layer being added is a polyline spatial type.  The test was run with a feature class containing 1188 features and again with a feature class containing 81267 features also with no appreciable difference.  The layer is file geodatabased and is on the local drive.

I ran the code sample below in VS2015 six times with the loop count changed and successive uncommenting of the tests:

             Test                                                          25 layers ms    50 layer ms

          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

          1: CreateLayer only:                                           8905            16990

          2: CreateLayer + FeatureLayer:                         8998             16817

          3: CreateLayer + FeatureLayer + Selectable:   11241            22149

        // For demonstrating the ArcGIS Pro slow map layer creation issue.  We are

        // trying to create a map containing 50 layers.  The test was run on Pro 1.4.

        internal static async Task LayerPerformanceTest()

        {

            ArcGIS.Desktop.Mapping.Map map = null;

            int ms = 0; // for performance test in milliseconds. 

            Task loadMap = QueuedTask.Run(() =>

            {

                //  Create new map  and set it's spatial ref.

                map = MapFactory.CreateMap("LayerTest");

                SpatialReference sr = SpatialReferenceBuilder.CreateSpatialReference(2227);  

                map.SetSpatialReference(sr);

 

                // Create a grouplayer to contain the newly created layers.

                GroupLayer groupLayer = GetOrCreateGroupLayer(map);

 

                // Append the same layer 50 times.

 

                string url = "c:\\Data\\COA\\FeatureEsri\\CadasterCogo.gdb\\ASR_RowLine";

 

                DateTime dt1 = DateTime.Now;

                for (int i = 0; i < 50; i++)

                {

                    // Test 1:

                    LayerFactory.CreateLayer(new Uri(url), groupLayer, 0, "Layer " + i.ToString());

                    // Test 2, add:

                    // FeatureLayer featureLayer = groupLayer.Layers[0] as FeatureLayer;

 

                    // Test 3 add:

                    // var cimFeatureDefinition = featureLayer.GetDefinition() as ArcGIS.Core.CIM.CIMFeatureLayer;

                    // cimFeatureDefinition.Selectable = false;

                    // featureLayer.SetDefinition(cimFeatureDefinition);

                }

 

                DateTime dt2 = DateTime.Now;

                TimeSpan span = dt2 - dt1;

                ms = (int)span.TotalMilliseconds;

            });

 

            // Wait (not blocking) until the task is done.  (loadMap.Wait() blocks).

            await loadMap;

 

            // Add the new map to the panes collection.

            var newPane = await ArcGIS.Desktop.Framework.FrameworkApplication.Panes.CreateMapPaneAsync(map);

        }

 

1 Reply
NarelleChedzey
Esri Contributor

Hello, 

Thank you for your post.  I have used your code in an ArcGIS Pro add-in and reviewed the performance.  I used a polyline feature class from a file geodatabase containing approximately 8300 features - appending it 50 times to a group layer within a new map.   Whilst I was not able to exactly duplicate your results, I did see some causes for concern in the performance.

I performed the test on both ArcGIS Pro 1.4.1 and our soon-to-be-released 2.0 version.  There are some performance improvements in 2.0 over 1.4.1  (about 20% faster in my testing scenarios). 

Additionally, there are 2 improvements you can make in your code.  Specifically change your loop to be the following 

                for (int i = 0; i < 50; i++)

                {

                    FeatureLayer featureLayer = LayerFactory.CreateLayer(new Uri(url), groupLayer, 0, "Layer " + i.ToString()) as FeatureLayer;

                    featureLayer.SetSelectable(false);

                }

1. By using the return value from LayerFactory.CreateLayer you can avoid the (admittedly small) time required to access the layer from the map. 

2. Casting this return value to a FeatureLayer and then using the SetSelectable function minimizes the traffic between the managed and native tier of the application code to a single call.   This is preferable and better than the GetDefinition, SetDefinition functions which will message between the managed and native tier twice.  

I expect you will see some improvements, mostly as a result of the second change, especially as that occurs within the 50x loop. 

I have also passed this item to the appropriate testing and development teams for further investigation.  Should I receive any further information I will post it here. 

Regards

Narelle Chedzey

SDK Team