draw a million or more small lines. data set updated at 1-10Hz

4409
5
Jump to solution
03-22-2016 08:58 AM
Highlighted
New Contributor III

I need to draw a million or more small lines. The set of lines to draw is updated typically at a rate of 1-10Hz. I've been using a graphics layer for this. At over 1GB, the memory usage is unacceptable for even just 100,000 lines. What's the recommended approach?

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
New Contributor III

I ended up writing my own rendering stack. The performance was good enough despite some cumbersome code to interface with the runtime. In some experiments, my solution used 50% memory for 15x the data. I think a generic "geometry layer" (just drawing primitives, no hit testing or other support) solution from Esri could easily see 6x improvement in memory usage over graphics layer.

View solution in original post

Reply
0 Kudos
5 Replies
Highlighted
Esri Frequent Contributor

Hi,

To help us understand the context, please can you describe your use case?

Please also attach a simple sample which demonstrates what you are doing now. This will enable us to make specific recommendations on how you can optimize the performance.

Cheers

Mike

Reply
0 Kudos
Highlighted
New Contributor III

Hi Mike, the use case is plotting where a sonar is/was and how far it was looking. The requirement is to comfortably plot a few days of this data. A GPS update rate of a few Hz translates into on the order of a million little lines. The sonar looks left and right "port and starboard". Each side needs to be colored differently.The length of the lines are typically 10-500meters. I need to be able to plot "live" as the points are coming in and also from recording.

Sample code:

  class Example

  {

    const string uniqueKey = "side";

    const int uniquePort = 0;

    const int uniqueStar = 1;

    readonly GraphicsLayer layer;

    public Example()

    {

      var renderer = new UniqueValueRenderer();

      layer = new GraphicsLayer()

      {

        Renderer = renderer,

        RenderingMode = GraphicsRenderingMode.Static,

      };

      renderer.Fields.Add(uniqueKey);

      renderer.Infos = new UniqueValueInfoCollection()

      {

        new UniqueValueInfo(uniquePort, new SimpleLineSymbol()

          { Color = Colors.Green, Style = SimpleLineStyle.Solid, Width = 1 } ),

        new UniqueValueInfo(uniqueStar, new SimpleLineSymbol()

          { Color = Colors.Red, Style = SimpleLineStyle.Solid, Width = 1 } )

      };

    }

    static Graphic Line(int uniqueVal, double direction, double meters, MapPoint innerPoint)

    {

      var outerPoint = GeometryEngine.GeodesicMove(innerPoint, meters, LinearUnits.Meters, direction);

      var line = new Polyline(new MapPoint[] { innerPoint, outerPoint });

      var attributesForUniqueValueRenderer =

        new KeyValuePair<string, object>[] {

          new KeyValuePair<string, object>(uniqueKey, uniqueVal) };

      return new Graphic(line, attributesForUniqueValueRenderer);

    }

    static void CreateGraphics(...other params..., ref List<Graphic> list)

    {

      ... add to list by eventually calling Line()...     

    }

    public void Add(...)

    {

      List<Graphic> graphics = null;

      CreateGraphics(..., ref graphics);

      if (graphics != null)

      {

        layer.Dispatcher.InvokeAsync(() =>

        {

          if (layer.Status == LayerStatus.Initialized)

            layer.Graphics.AddRange(graphics);

        });

      }

    }

  }

Reply
0 Kudos
Highlighted
Esri Frequent Contributor

Hi,

Thanks for providing the repro code: we have been conducting some tests based on your scenario. From looking at your code, you are already taking advantage of the usual optimizations we recommend such as using the Static graphics rendering mode and using a renderer rather than per-graphic symbols. From our testing, with 100,000 lines memory was around 500MB which increased to 4GB with 1,000,000 lines.

It would be interesting to try the same approach with a runtime geodatabase (needs to originate from a service initially in order to be editable) and see if that offers an performance benefits. The frequency of updates (1-10 times per second) may come into play then rather than the memory consumption.

I'll continue to investigate with our internal architecture team to see if there are an additional tweaks which can be made to your approach.

Cheers

Mike

Reply
0 Kudos
Highlighted
New Contributor III

Thanks for looking into this, Mike. Can you point me to some docs or examples on the geodatabase approach? Specifically, I'd like to know how to "bootstrap"/get-the-initial geodatabase, how to update it, and how to prompt some rendering (using local server?) of the data. I've seen examples on rendering with "dynamic layers" with local server which I think is the approach to try because I am assuming a feature layer would not be much better than graphics in terms of memory usage.

Reply
0 Kudos
Highlighted
New Contributor III

I ended up writing my own rendering stack. The performance was good enough despite some cumbersome code to interface with the runtime. In some experiments, my solution used 50% memory for 15x the data. I think a generic "geometry layer" (just drawing primitives, no hit testing or other support) solution from Esri could easily see 6x improvement in memory usage over graphics layer.

View solution in original post

Reply
0 Kudos