Hardware specifications, choices within your application development environment, and the ArcGIS Runtime each contribute to how well your application will perform. You should consider each of these when trying to improve performance.
The Runtime SDKs are built to be fast, but there are still ways you can improve performance by working with the items described below, such as spatial reference and rendering modes.
A video presentation of this topic's information is available, Squeezing every ounce of performance from ArcGIS Runtime.
When working with online services, it's important to choose the spatial reference for your map early and ensure data and layers are stored, managed, and shared in the same spatial reference. This practice lets you avoid having data be reprojected on the server. Reprojecting data is detrimental to performance.
As the topic Layer Types describes, multiple types of layers are available in the API depending on the content you want to display in the map. Each type of layer has specific functional characteristics that determine the appropriate layer type for your content. With those characteristics also come a set of performance characteristics you must consider when designing your map.
Another factor to consider is the number of layers in the map. This is typically expected to be in the range of 1s and 10s of layers. The precise number of layers that can be added to the map while still being able to meet the performance expectations of your users is not a simple calculation, because it depends on many factors. Some of these factors involve the performance characteristics mentioned earlier. Other factors are noted in this topic, such as the volume of information in a layer and the way in which you symbolize the layer. Additionally, the processor speed, memory, and graphics hardware resources of the device, or devices, on which you intend to deploy the application significantly affect the application performance.
Graphics layer rendering modes
When choosing between dynamic and static rendering modes for graphics layers, keep the following considerations in mind:
- Dynamic rendering mode—In this mode, which is good in most use cases, the entire graphic representation is stored on the GPU. This mode is especially good for moving objects, as individual graphic changes can be efficiently applied directly to GPU state, resulting in a seamless experience. However, the volume of graphics has a direct impact on (GPU) resources, and the number and complexity of graphics that can be rendered in this mode is dependent on the power of the GPU and the amount of GPU memory.
- Static rendering mode—Use this mode for stationary graphics, complex geometries, and very large numbers of polygons. Volume of graphics has little impact on frame render time (scales well) and pushes a constant GPU payload. However, rendering graphic updates is CPU/system memory intensive, which can have an impact on device battery life.
Layer type and rendering mode
Layers are arranged bottom to top in the map, usually with the basemap layer at the bottom having a layer index of 0. Other layers are stacked on top of the base layer with ascending layer index values. As layers are added to the map, try to keep layers with the same type and rendering mode next to each other in the stack. Some examples follow:
- Keep feature layers together—They use the underlying static rendering mode available as an option on graphics layers.
- Keep graphics layers with static rendering mode together.
Adhering to these groupings allows the Runtime to optimize data transfer to the GPU. When layers with static rendering mode are rendered to an image on the CPU, the Runtime can stack the images for multiple adjacent layers together and push the stack as a single set of textures to the GPU. In contrast, when static layers are not adjacent to one another, the Runtime must generate multiple images to preserve graphics' visibility ordering. In this case, multiple sets of textures must be pushed for each extent change. Layer order does not affect layers rendering in dynamic mode because all resources for the layers reside on the GPU, and the GPU can easily arrange these items when drawing.
One graphics layer per geometry type
It's recommended that you create one graphics layer for each type of geometry to improve rendering performance on graphics layers with dynamic rendering mode. This practice results in fewer GPU switches and flushes, which are necessary when rendering different geometry types on the same layer.
Polygon feature layers
For polygon feature layers (ArcGISFeatureLayer), where the number of polygons and polygon complexity (fill texture, outline texture, and so on) can be unknown, it’s typically better to use static rendering mode.
Number of graphics
Many variables are at play when it comes to the number of graphics that can be rendered quickly on the map. The major factors to consider are:
- The complexity of the graphics (large numbers of vertices)
- The target device
- The mode you use (dynamic or static)
- The end-user experience
In dynamic mode, graphics are constantly rendered, giving the map a seamless look and feel when interacting with it. The entire graphic representation resides on the GPU, so as the number of graphics increases, the GPU has to work harder to render. A large number of graphics can impact how responsive the map is to user interaction.
Static mode renders graphics when needed (when the map extent changes) and offloads a significant portion of the graphical processing onto the CPU. As a result, less work is required by the GPU to draw the graphics, and the GPU can spend its resources on allowing the map UI to remain interactive. However, heavy use of the CPU can impact battery life on a device.
You can add graphics individually to the graphic collection on a graphics layer, or you can add graphics in bulk. The Runtime has optimization checks on bulk additions for creating new textures for unique graphics and only pushes those textures to the GPU once. This optimization typically makes adding graphics two to five times faster.
Graphics within graphics layers can be symbolized with either symbols or renderers. For graphics layers with small numbers of graphics, it's acceptable to assign an individual symbol to each graphic. The Runtime will attempt to reuse duplicate symbols where it can, but there is an overhead in this calculation.
For larger numbers of graphics, you should always use a renderer, which ensures the reuse of symbol instances. Another benefit of using renderers is the efficiency related to adding new graphics. Since symbols are defined on the renderer, the API has less data to push to the Runtime. Individual graphics can have symbols assigned even when the layer also has a renderer. In this scenario, the symbol typically takes precedence, although in some cases, it's possible to control this behavior via the API. For more information on symbols and renderers, see Symbols and renderers.
Graphics layers can have both symbols and renderers assigned to them. For graphics layers with small numbers of graphics, it's acceptable to use individual symbols on each graphic. The Runtime will attempt to reuse duplicate symbols where it can, but there's an overhead in this calculation.
For larger numbers of graphics, you should always use a renderer, where unique symbol reuse is ensured. Another benefit of using a renderer is the efficiency related to adding new graphics. Since symbols are defined on the renderer, the API can push less data to the Runtime.
You can improve performance by rendering only the graphics that make sense for a scale range and turn off the graphics that don't. You do this by setting a scale range on a layer to indicate at which scales (zoom level range) you want that layer to display. For example, when your user zooms out to a country boundary, you can have the detailed bus routes layer turn off automatically.
Setting this scale range, also known as setting scale dependency, not only makes the map less cluttered and easier to use, but it also conserves GPU (in dynamic mode) and CPU (in static mode) resources, because unneeded graphics aren't rendered.
- A video presentation of this topic's information is available, Squeezing every ounce of performance from ArcGIS Runtime.
- Maps and layers—Describes layer types and includes information on how they relate to performance.
Application development environment
The hardware that you choose may mean you that you have more than one application development environment choice. Each of these will provide you will different ways to improve performance.
On mobile devices where you have limited resources and variable network speed it is advisable to perform long running tasks on a background thread.
However, since threads consume device resources, you still do need to pay particular attention to minimizing the amount of threads that are created.
QML is a declarative language and as such is not reliant on sequence or ordering for code execution. Immediately when a property changes, and elements that are bound to that property will also change. Property binding is a very efficient way to enact user interface changes. Some examples include:
- defining the size of a graphic element based on the size of another
- positioning of elements with anchors bound to other elements
Hardware is designed with functionality and specific needs in mind. Be sure to understand the capabilities of your hardware before adding the complexities of an application environment and the ArcGIS Runtime to your requirements.
Mobile devices have less processor and memory resources compared to standard desktop machines. For this reason, applications need to be developed to run in an efficient manner.
Mobile devices often use 3G or sometimes lower speed radio communication networks to obtain and transfer data. The speed of these networks vary but are much slower (in terms of data per second) than wired or wireless networks. Due to this network latency, small requests can take time to return, which makes your application seem sluggish. Therefore, you need to carefully manage the total amount of data and the number of network requests submitted by your mobile application. As an example, it may be more efficient to send a single large request for data rather than multiple small requests. Changing the layer types, application functions, or the flow of your application can also affect network speed.
If your mobile application users are always in the range of a wireless network, your application can retrieve and submit larger amounts of data. However, even in this scenario, it's always good practice to remember the amount of data and number of requests your application uses, whatever the bandwidth.
By understanding the characteristics of the different types of map layers in the API, you can determine the best layers for your needs and ensure that your application performs for your users.
Some application users may only have intermittent network access, such as intermittent 3G access due to working in remote areas or daily access to a wireless network for synchronizing data. If this is the case, local storage usage is important. The application can be designed to connect to the server to retrieve data the user needs, then store this data on disk or in a local SQLite database. Applications need to be developed robustly with this in mind, because the network connection can be dropped anytime. Functions need to fail gracefully, and any long running application transactions may need to be rolled back.