Poor performance when creating polylines

2514
9
06-07-2017 07:16 AM
RehmSoftware
Regular Contributor

Hello,

I'm currently testing the performance of ArcGis Pro regarding how fast it is to create and draw polylines or polygons (the reason is that I'm comparing the performance to AutoCAD in order to find out whether we could port our software product to the ArcGis Pro platform).

I came up with a sample code that draws about 10.000 triangles on an existing feature layer. But I was rather underwhelmed by the performance as it took about 24 seconds on my machine (i7-3930k, 24GB RAM, nVidia GTX 650 Ti). The same task in AutoCAD only took 0.1 seconds...

But since I'm new to programming with ArcGis I might have made a stupid mistake that slows down my code a lot. So I'd be happy if someone with more knowledge could look over it and give me some hints whether I'm doing something wrong.

This is my code:

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using ArcGIS.Core.Data;

using ArcGIS.Core.Geometry;

using ArcGIS.Desktop.Core;

using ArcGIS.Desktop.Editing;

using ArcGIS.Desktop.Framework;

using ArcGIS.Desktop.Framework.Contracts;

using ArcGIS.Desktop.Framework.Dialogs;

using ArcGIS.Desktop.Framework.Threading.Tasks;

using ArcGIS.Desktop.Mapping;

 

namespace ProAppModule1 {

    internal class createPolylines : Button {

        protected override async void OnClick() {

            var sw = new Stopwatch();

            sw.Start();

            await this.DrawPolylines();

            sw.Stop();

            MessageBox.Show(String.Format("Time elapsed: {0:t}", sw.Elapsed));

        }

 

        private Task<bool> DrawPolylines() {

            var activeMapView = MapView.Active;

            var extent = activeMapView.Extent;

 

            //Draw about 10000 triangles. Use sqrt to have the same number of triangles in width and height even though we'll end up with more than 10000 triangles in the end

            int numTriangles = 10000;

            int rows, cols;

            rows = cols = (int)Math.Ceiling(Math.Sqrt(numTriangles));

 

            double triangleWidth = extent.Width / cols;

            double triangleHeight = extent.Height / rows;

 

            var polylineFeatureLayer = this.GetFeatureLayerByName(activeMapView.Map, "My_Polyline");

            return QueuedTask.Run(() => {

                var featureClass = polylineFeatureLayer.GetTable() as FeatureClass;

                var polylineDefinition = featureClass.GetDefinition() as FeatureClassDefinition;

                var spatialReference = polylineDefinition.GetSpatialReference();

 

                var createOperation = new EditOperation();

                createOperation.Name = "Draw Polylines";

                createOperation.SelectNewFeatures = false;

 

                var coordinates = new Coordinate[4];

                double x = extent.XMin;

                double y = extent.YMin;

                for (int i = 0; i < rows; ++i) {

                    for (int j = 0; j < cols; ++j) {

                        coordinates[0] = new Coordinate(x, y, 0.0);

                        coordinates[1] = new Coordinate(x + triangleWidth, y, 0.0);

                        coordinates[2] = new Coordinate(x + triangleWidth, y + triangleHeight, 0.0);

                        coordinates[3] = coordinates[0];

 

                        var polyline = PolylineBuilder.CreatePolyline(coordinates, spatialReference);

                        createOperation.Create(polylineFeatureLayer, polyline);

                        x += triangleWidth;

                    }

 

                    x = extent.XMin;

                    y += triangleHeight;

                }

 

                return createOperation.ExecuteAsync();

            });

        }

 

        private FeatureLayer GetFeatureLayerByName(Map map, string layerName) {

            var featureLayers = map.GetLayersAsFlattenedList().OfType<FeatureLayer>();

            foreach (var layer in featureLayers) {

                if (layer.Name.Equals(layerName, StringComparison.CurrentCultureIgnoreCase))

                    return layer;

            }

 

            return null;

        }

    }

}

Thanks in advance!

Christian

0 Kudos
9 Replies
CharlesMacleod
Esri Regular Contributor

Thanks for this Christian, Your code looks fine. We can reproduce. We will look at optimizations for both PolylineBuilder.CreatePolyline and createOperation.Create. It could be, too, that a single builder create call that creates polyline_s_ (plural) in one shot (not a loop) would be a useful enhancement. 

RehmSoftware
Regular Contributor

Hi Charles,

thanks for your reply. I'm glad you could reproduce the issue and that your're looking into it. I'll hold out with further testing until the optimizations are implemented.

Best Regards,

Christian

0 Kudos
RehmSoftware
Regular Contributor

Hi Charles,

I do have one follow-up question, if you don't mind. I'm wondering why ArcGis Pro itself can draw so much faster.. for example the tool "tin triangle (3d-analyst)" creates and draws a lot of polygons really fast (depending on the input tin of course).. and I'm curious how can this be so fast and my code so slow? Or is this tool using an entirely different way of drawing the polygons?

Thanks in advance and Best Regards,

Christian

0 Kudos
CharlesMacleod
Esri Regular Contributor

The tool is creating the polygons entirely in native code (c++). There is no interop between managed and native. I am thinking that once you had ~made~ the polygons in your code they drew equally fast....that the performance concern was in their creation....

RehmSoftware
Regular Contributor

Okay, so the creation of the polygons is what's taking so long and not the drawing per se... thanks for the explanation! Is there a way I could speed up the creation process? Or do I just have to wait until the SDK offers more performance like you mentioned in your first answer?

0 Kudos
CharlesMacleod
Esri Regular Contributor

Not via the API. You will need the improvements

0 Kudos
RehmSoftware
Regular Contributor

Okay, I figured it would be like that.. can you give me an (even very) rough estimate when I can expect the API/SDK improvements? Thanks!

0 Kudos
RehmSoftware
Regular Contributor

Fast forward two and a half years I've tested my example above again on the same machine as back then and with ArcGIS Pro 2.5.0 and the SDK Version 2.3.0.15769..

The code now takes about 7 seconds to execute for 10k polylines - which is quite an improvement over the original 24s. 20k polylines take about 14 seconds... I guess the whole thing is O(n).

To be honest I find it still too slow, especially since we're talking about small values of n. In a real life scenario I have to draw 500k polylines (or polygons, whatever) at a time.

I'm not asking for OpenGL drawing speed here, but as the major portion of execution time is spent creating the geometries it would be awesome to have a "batch creation" mode for such a large number of geometries. Are there any plans to speed up the drawing/creation process further? Because right now I have a tough time selling our ArcGIS Pro based software product to our customers because of such performance limitations.

Thanks in advance

0 Kudos
JeremyWiles
Occasional Contributor

Has there been any improvements to this poor performance since then?  I haven't seen any new replies since 2020.

ArcObjects read and wrote each vertex to a database at least 5x the speed.  I cannot run these operations any faster even with async/await capabilities, unfortunately.

Thanks.

0 Kudos