Select to view content in your preferred language

MapPoint woes

550
2
Jump to solution
09-02-2022 12:15 PM
MichaelDavis3
Frequent Contributor

We've got an in-progress Xamarin Forms 5 app where we need to load ~48k structure points from Entity Framework/sqlite (via direct SQL query) and present them on a map via Graphics Overlays.

The MapPoint constructor seems to be rather expensive, taking roughly 20 seconds to cycle through the structures.  Adding the created MapPoints to Graphics Overlays and presenting them on the map is extremely fast, it's just the initial creation of the points that is slowing things down.

We've looked into somehow persisting the MapPoint object however despite having JSON import/export functions the object itself is not serializable so we can't keep them around between sessions.  This is put us in a bit of a quandary where we are having to pull UI tricks and alter workflows do disguise the poor performance when loading the structures into the map.

Any ideas on how we might be able store and retrieve MapPoint objects on mobile?  Any chance we might be able to actually serialize geometry objects?  Our spec requires licensing at the Lite level so we can't do a local Mobile Geodatabase to stash points, and we've tried various alternate methods of generating points (PointBuilder, from JSON, from Coordinate String) but they all seem to have the same performance issue.

0 Kudos
1 Solution

Accepted Solutions
MatveiStefarov
Esri Contributor

Hello Michael!  In general, the fastest way to create point Graphics in Runtime is:

  1. Construct a Graphic using the attribute-only constructor.
  2. Construct a MapPoint from coordinates and set Graphic.Geometry property.
  3. Populate a List with Graphics and then add them to a GraphicsOverlay all at once.

Some performance best practices and micro-optimizations to follow:

  • Use a Renderer on the GraphicsOverlay instead of manually assigning a Symbol to each Graphic.
  • Use as few attributes as possible for each Graphic.  Only set attributes necessary to identify and render the Graphic.  It's more efficient to keep other attributes in SQLite or at least in a Dictionary, than to copy them into Graphics.  EF queries should also get faster if fewer attributes need to be projected.
  • Use Graphic constructor that takes a Dictionary of attributes instead of individually adding them on the Attributes after construction.
  • Avoid MapPointBuilder if performance matters -- it's significantly slower than constructing MapPoints directly, and only exists for the sake of rounding out GeometryBuilder API.
  • Use a SpatialReference that matches the Map, ideally a common one (e.g. SpatialReferences.Wgs84 or SpatialReferences.WebMercator).  This avoids the overhead of datum conversion and reprojection.
  • To create Graphic with point geometry, prefer setting the Graphic.Geometry property.  This setter uses a special optimized codepath, originally created with animated/moving Graphics in mind, that's even faster than Graphic constructors that take Geometry. 
  • Use GraphicsOverlay.Graphics.AddRange(...) instead of adding graphics one at a time.
  • Upgrade to modern versions of .NET if possible -- the new net6.0 runtime is significantly faster than .NET Framework and Mono.

You can find more performance advice in this recently-updated developer guide topic: Performance considerations.  You can also check out this 10-minute demo from DevSummit 2022 that focused on Graphic performance (relevant part starts around 22:30).

I would also encourage you to measure which parts of the process account for most time, and to check the official EFCore performance tips.  I would be glad to look into specifics of your app to see how we can help achieve better performance!

View solution in original post

0 Kudos
2 Replies
MatveiStefarov
Esri Contributor

Hello Michael!  In general, the fastest way to create point Graphics in Runtime is:

  1. Construct a Graphic using the attribute-only constructor.
  2. Construct a MapPoint from coordinates and set Graphic.Geometry property.
  3. Populate a List with Graphics and then add them to a GraphicsOverlay all at once.

Some performance best practices and micro-optimizations to follow:

  • Use a Renderer on the GraphicsOverlay instead of manually assigning a Symbol to each Graphic.
  • Use as few attributes as possible for each Graphic.  Only set attributes necessary to identify and render the Graphic.  It's more efficient to keep other attributes in SQLite or at least in a Dictionary, than to copy them into Graphics.  EF queries should also get faster if fewer attributes need to be projected.
  • Use Graphic constructor that takes a Dictionary of attributes instead of individually adding them on the Attributes after construction.
  • Avoid MapPointBuilder if performance matters -- it's significantly slower than constructing MapPoints directly, and only exists for the sake of rounding out GeometryBuilder API.
  • Use a SpatialReference that matches the Map, ideally a common one (e.g. SpatialReferences.Wgs84 or SpatialReferences.WebMercator).  This avoids the overhead of datum conversion and reprojection.
  • To create Graphic with point geometry, prefer setting the Graphic.Geometry property.  This setter uses a special optimized codepath, originally created with animated/moving Graphics in mind, that's even faster than Graphic constructors that take Geometry. 
  • Use GraphicsOverlay.Graphics.AddRange(...) instead of adding graphics one at a time.
  • Upgrade to modern versions of .NET if possible -- the new net6.0 runtime is significantly faster than .NET Framework and Mono.

You can find more performance advice in this recently-updated developer guide topic: Performance considerations.  You can also check out this 10-minute demo from DevSummit 2022 that focused on Graphic performance (relevant part starts around 22:30).

I would also encourage you to measure which parts of the process account for most time, and to check the official EFCore performance tips.  I would be glad to look into specifics of your app to see how we can help achieve better performance!

0 Kudos
MichaelDavis3
Frequent Contributor

Thanks for your response - implemented all of your suggestions (including minimizing fields coming from EF) and brought the load time down from 20-40sec to 2 seconds flat.

Unfortunately this project requires AppCenter and MSAL - which are total no-go for MAUI right now so .net 6 is off the table.  Looking forward to checking out the performance improvements once MAUI is a little more mature.. maybe .net 7 at this point.

0 Kudos