Azure Maps SVG Performance Issue

Nilesh Khonde 60 Reputation points
2025-02-19T13:56:01.3333333+00:00

Title: Issues with Rendering 1000+ Filtered CRM Records with Custom SVG Icons on Azure Map

Body: I'm working on an Azure sample project where I filter CRM records based on specific criteria and then dynamically generate custom SVG icons (with new colors) for each record. The intended functionality is to display these records on an Azure-based map with their respective icons.

However, when the scenario involves more than 1000 records, I encounter the following issues:

  • Incomplete Plotting: Not all records are plotted on the map with the expected custom SVG icons.
  • Performance Degradation: The map sometimes becomes unresponsive or gets “stuck” after processing a large dataset.

What I've Tried:

  • Verified that the filter criteria correctly returns the expected dataset.
  • Checked the SVG icon generation logic to ensure colors and icon structure are applied properly.

Questions:

  1. Are there known limitations or performance concerns when rendering over 1000 custom SVG icons on Azure maps?
  2. What best practices or optimizations can be implemented to efficiently handle such large datasets in this context?
  3. Has anyone encountered similar issues when dynamically generating icons based on filtered CRM records?

Any insights or recommendations on how to address these performance bottlenecks and ensure all records are plotted correctly would be greatly appreciated.

Looking forward to your suggestions and feedback.

Azure Maps
Azure Maps
An Azure service that provides geospatial APIs to add maps, spatial analytics, and mobility solutions to apps.
792 questions
{count} votes

1 answer

Sort by: Most helpful
  1. rbrundritt 19,306 Reputation points Microsoft Employee
    2025-02-19T18:41:33.77+00:00

    Given that you are working with 1000+ rows of data I assume you are using the approach of loading the SVG into the maps image sprite, then rendering the data using the Symbol layer as that would be the only performant way to render a 1000+ points on the map with custom icons (HTML markers support SVGs as well but performance impacts start occurring when you get over a couple hundred shapes).

    With the above in mind it sounds like every data point has its own unique SVG, so you are loading in thousands of SVG's into the maps image sprite. This simply won't work. The image sprite is a single large image that is a sprite sheet and has limited space. The SVG's are converted into an image, added to the sprite sheet, then the sprite sheet is transferred to the GPU for rendering. So, you will hit a point where you have added too many SVG's to the image sprite and either additional SVGs won't be added and thus not display on the map. Note, that there is no set max number of images/SVG's that can be added to image sprite, it's based on available area in the image sprite, so the size of your SVG's/images would dictate how many would fit.

    Now let's look at this from a performance perspective:

    • If every data point has a unique SVG, that means there are thousands of SVG's being loaded into the page. That alone is a ton of data and can quickly slow things down from a page load perspective. This would also use up a lot of memory.
    • I suspect that the data driven style you are using to then select the right icon in the symbol layer is a really long "match" expression which would mean a ton of processing at render time and also mean a lot of data to be passed to the GPU. Alternatively, you could have a unique ID for each data point and used that as the ID for the SVG's when adding to them to the image sprite, then use a simple "get" expression on the ID. That would be better than a match expression from a performance perspective, but you would still run into the limit on the size of the image sprite (# of SVG's).

    Now let's look at how to resolve these issues and get really good performance with some minor change in approach:

    First off, are your SVG's truly unique? Ignore the color and the size for a moment, is the shape of the SVG for each data point truly unique or is there a small subset of shapes that your SVG's represent (this is usually the case unless you are generating pie charts or something). If you have, a couple dozen unique SVG shapes, these could be loaded directly into the map separate from the data points. The size of this data would be much smaller, so page load would be faster, and since there is a lot less SVG's to load into the map, the time to add them to the image sprite would be significantly less.

    • The symbol layer already has a "size" option which you can use to scale the icons as needed. So, if you have the same SVG shape used across multiple data points, adding a property to scale your SVG's accordingly and using the with the "size" option would help reduce the number of SVG's you need to load. Now this may not mean you need a new data column in your data as there must be some business logic that is being used today to determine the scale, for example it may be relative to some metric in the data like revenue. This business logic could be added as a data driven style on the "size" option.
    • When it comes to color, a common approach is to use two layers to render your points and separate the coloring from the icon shape. The bottom layer would be a bubble layer where you can use a data driven style based on some metric in your data to set the color of the bubble (similar to the scale/size logic in the previous point which can also be used with this layer). The second layer would be a SVG layer that loads in the truly unique subset of SVG shapes over top of the bubble layer. Often in this case the SVG's are black so they stand out when overlaid above the bubble layer. You can then use a property in your data and a data driven expression on the image option of the symbol layer. You might think that rendering two layers would make things slower, but it won't in this case. Since there are a lot less unique SVG shapes, the GPU is able to optimize how it renders those using a process called "instancing" and drastically reducing draw calls which is the most expensive part in a rendering pipeline. This does means that each data point would be represented by a colored circle/bubble, with the SVG shape drawn on top. This may mean a bit of a change in how your data looks, but provides a couple of key benefits; drastic improvement in performance, and allows you to dynamically change the color of data points based on changes in your data (no need to regenerate the SVG data in your database, simply update the metric column used with your business logic and the next time your data is loaded into the map it will automatically update how it renders).

    Doing the above would mean loading the subset of unique SVG's shapes you have into the map separate from your data (they would be a part of your app, not stored with your data). This would also reduce the overall storage size of your database and make things more scalable and cheaper in the long run. Data driven styling would leverage other data columns in your data along with your business logic for choosing which color to assign to the bubble layer, which SVG shape to select in the symbol layer, and if needed, how to scale these.

    A common way to determine which icon to use is a category type property. For example, if your data represents different types of businesses, you might categorize them like restaurant, gas station, grocery store and store just the category info in your data with each data point. In this case you would have 3 images/SVG's that you would into the map sprite, one for each category and use a "match" expression on the category data column. Here is a similar code sample: https://samples.azuremaps.com/?sample=data-driven-symbol-icons

    Similarly, you may have another metric in your data that can be used to determine the color, for example revenue. You can then create a data driven style with your business logic (even complex logic like gradient, or something involving a custom formula) to then choose the color you want. The color might be chosen from a set of predetermined colors, or you could have complex logic that generates and "rgb" value (or even have the rgb/hex color value stored as a property in your data if the color will rarely change). Here is a similar sample: https://samples.azuremaps.com/?sample=data-driven-bubble-layer-styling Note, in this sample a symbol layer is also used in combination with the bubble layer. In this case the image is hidden and only the text is displayed, but that's a minor change. This sample is pretty close to what you will end up doing.

    I've used the approach above in hundreds of apps over the last decade with data sets of well over hundred thousand points.

    The above is the most common approach used for optimizing this type of scenario, however it isn't the only one. Here are a couple others I've encounter in the past which have their pros and cons;

    1. SVG's can often converted into a font files. This means you could create a custom font and use that with the text options of a symbol layer. This would allow for hundreds of unique SVG shapes, and you can use font color and size to customize them. This performs well, but it is a lot more complex to get working and more difficult to maintain.
    2. Render the data server side as a custom tile layer. This approach can be used to render billions of data points, all uniquely, with decent performance. However, this is a lot more work to setup and generates more costs as you have a backend service that will need a lot of compute power or GPUs.
    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.