Select to view content in your preferred language

Real Time Client Side performance

577
2
Jump to solution
03-18-2023 02:46 AM
JPichel
New Contributor II

Hi,

I am working on an web drone ground control station that uses ArcGIS Maps SDK for Javascript. The nature of the application makes it so I need to update multiple geometries and graphics several times per second (every time a telemetry message comes in, etc.). We mostly use FeatureLayer and GraphicsLayer for this, creating our graphics on the client side and updating them the same way.

When testing the performance of these update operations using firefox and chrome profilers, we have found that the best way to do this is to do something like this when updating a graphic already added to a GraphicsLayer:

 

const point = new Point({
spatialReference: SPATIAL_REFERENCE,
latitude: telemetry.latitude,
longitude: telemetry.longitude,
hasZ: true,
z: telemetry.relativeAltitude,
})
const symbolLayer = new ObjectSymbol3DLayer({
height: 1,
anchor: 'relative',
anchorPosition: {
x: 0,
y: 0,
z: -0.2,
},
resource: {
href: './drone3D.glb'
},
heading: telemetry.heading + 180,
tilt: telemetry.pitch,
roll: telemetry.roll,
})
droneModel.geometry = point
droneModel.symbol = new PointSymbol3D({
symbolLayers: [
symbolLayer
]
})

As you can see, we have to create a new Point geometry and a new PointSymbol3D with its corresponding ObjectSymbol3DLayer that loads the drone model resource.

This seems to be the most optimal way to do these kinds of updates, since the API as for now doesn't allow rerendering of the graphics when directly modifying the already existing geometries/symbols.

Even so, our rendering logic doesn't have the best performance when dealing with 50 updates/s, causing update delays that sometimes crash the tab. The solution we found for this particular case updating the drone model, is to cap the updates to 4 times per second.

Still, we see that when panning around the SceneView, when the map rerenders, our render updates sometimes stop, causing lag while the map is rerendering itself.

I guess my question is do you have some performance tip for this kind of application? ArcGIS works very well even when having thousands of features or graphics already plotted, the problem seems to be the fact we are updating a few graphics several times per second.

Thanks a lot

1 Solution

Accepted Solutions
ArnoFiva
Esri Contributor

Thanks for the detailed description! There are various things that can influence the performance of your animation in 3D. Without seeing the code, I'll list some of the general aspects to check:

  • What mechanism do you use to trigger an update? Make sure to use the browser's built in requestAnimationFrame so you only perform updates when the browser is idle and has time to render it. This will also throttle the number of updates when e.g. panning.

  • The size and complexity of your glb model (textures and triangles) will impact performance, but also make sure you create the PointSymbol3D and Object3DPointLayer instances at the beginning and reuse them in each update step. If you need to recreate them to change properties like the heading, use clone() instead of creating a new instance. This avoids having to reload the glb, even if it is cached.

  • Related to the previous point, that is one of the advantage of using FeatureLayer.applyEdits() over GraphicsLayer. By updating the heading/roll/tilt through attributes and using a RotationVariable for each of the attributes in the renderer, you automatically reuse the symbol.

  • With the latest version of the JavaScript SDK (4.26), instead of using a FeatureLayer, we recommend using a client side stream layer and push updates using StreamLayer.sendMessageToClient(). We've added this capability specifically for situations where you want to update your data very frequently (many times per second).

The use case you describe sounds very interesting and we would like to hear more about it, technically but also on a use case level, I'll get in touch via DM.

 

View solution in original post

2 Replies
ArnoFiva
Esri Contributor

Thanks for the detailed description! There are various things that can influence the performance of your animation in 3D. Without seeing the code, I'll list some of the general aspects to check:

  • What mechanism do you use to trigger an update? Make sure to use the browser's built in requestAnimationFrame so you only perform updates when the browser is idle and has time to render it. This will also throttle the number of updates when e.g. panning.

  • The size and complexity of your glb model (textures and triangles) will impact performance, but also make sure you create the PointSymbol3D and Object3DPointLayer instances at the beginning and reuse them in each update step. If you need to recreate them to change properties like the heading, use clone() instead of creating a new instance. This avoids having to reload the glb, even if it is cached.

  • Related to the previous point, that is one of the advantage of using FeatureLayer.applyEdits() over GraphicsLayer. By updating the heading/roll/tilt through attributes and using a RotationVariable for each of the attributes in the renderer, you automatically reuse the symbol.

  • With the latest version of the JavaScript SDK (4.26), instead of using a FeatureLayer, we recommend using a client side stream layer and push updates using StreamLayer.sendMessageToClient(). We've added this capability specifically for situations where you want to update your data very frequently (many times per second).

The use case you describe sounds very interesting and we would like to hear more about it, technically but also on a use case level, I'll get in touch via DM.

 

JPichel
New Contributor II

Hi Arno,

I am so sorry that I wasn't able to see your answer before. I lost access to my account for some time.

Silly error on my part 😁, I was indeed not using requestAnimationFrame but directly calling this updates, will try it out as soon as I can.

Also I didn't know about RotationVariables, nor did I know that you could use client side StreamLayers, I will try both approaches for other layers. Not sure if I will be able to do it for the drone layers since I have a mechanism in place where the drone graphic gets changed for a more detailed model when the camera is closer to it, that's why I was using the GraphicsLayer.

Thanks a lot for the amazing work! This will surely help the performance of my application!