Community Tip - Your Friends List is a way to easily have access to the community members that you interact with the most! X
Hi, I want to share a possible problem in my AR experiences. When there is a heavy data iteration (eg for loop through JSON metadata) while running the experience, the FPS goes very low.
How can I solve it?
Hi @GianVal ,
the question is what kind of iteration is it - I think such behavior could be normal if you do any iteration steps in nearly infinity loop.
So what you can do if the loop is doing some calculation which are not directly affecting widgets properties and display then you can try to call the calculation to second thread - e.g.
https://medium.com/jspoint/achieving-parallelism-in-javascript-using-web-workers-8f921f2d26db
https://www.w3schools.com/html/html5_webworkers.asp
https://web.dev/workers-basics/#toc-inlineworkers
Another points is to call in each iteration the call
$scope.$applyAsync();
or to call each iteration as function with $timeout service with / or without delay
So for example you can try something like this:
let myDelayPerItterationCall = 100; //so 100 millisecond per call delay
for(let i=0; i< verylargeNumber; i++)
{
$timeout(()=>{
myFunction1();
....
myFunctionN();
$scope.$applyAsync();
}, myDelayPerItterationCall *i) //end timeout call
} //end for loope
I apply a "showobject" method to ALL the parts of my structure. To do this I perform a for loop on the entire model metadata structure.
I know that is a huge computational load, but I will investigate on webworkers solution.
I tried with $scope.$applyAsync() and timeout method but they don't work.
if shoobject implies some call like this example:
name="model-1-/0/1/4"
if( isPreview())
tml3dRenderer.GetObject(name).GetWidget().SetVisibility(true);
else
tml3dRenderer.setProperties(name,{ hidden:false} );
then yes this requires time. In this case is better to set all properties and then call $scope.$applyAsync()
The question is also if you search is recursive - possibly your write to much things into stack
- I think for better performance you can split the search and set.
-first call the search and write all names of entities you want to set display to a list (also disable any prints to console - this make it very slow). Later go sequentially and set in simple loop the properties of the entities.
As mentioned this depends on you program and the size of the assembly and could be answered generally - and the point is that when we need to change the display of large numbers of assembly parts -this is something what still need time to refresh on mobile. There is not possible to use additional threads, I think
Yes, it's what I do. take data and put it into lists; that loop into that lists. Perhaps I should accept some seconds of low FPS I suppose...
Another way I could experiment is to monitor the FPS and show a sort of "loading" modal popup while the FPS is under a certain threshold. Do you know how to monitor the current FPS of the experience?
You may be able to use the preview with the browser developer tools to identify exactly which operations are causing the slowdown. For example, Chrome has a "Performance" tab that lets you profile JS code running to see where it's spending time. That can give you clues about how to optimize the code to reduce the effect on frame rate.
If you can't find a way to get a good framerate, you could add a spinner widget as a "busy" indicator during your data processing phase, to let the user know it's crunching some numbers and they should be patient until it's done. Set it to invisible by default, then when you start the data processing set it to visible, and set to invisible again when you're done. I've used this approach when dynamically switching sequences for a model, which can sometimes take a few seconds.
Thank you for the reply. The point is that I call the following method for all components (about 5000):
function show3DObject(name) {
tml3dRenderer.setProperties(name, { hidden: false });
}
The for loop where the method is called ends up pretty quickly (in fact I just placed a spinner on hold and it disappears in a few frames).
In my opinion, I need to place a spinner awaiting the resolution of the tml3drenderer promise, but obviously, I don't have access to that built-in method.
Ah, I see. It sounds like you need a way to suspend screen updates while you modify the item properties, and then resume so it's not constantly trying to update as you go. I'm not sure how that would work, or even if it's possible, given that you are calling the renderer directly. Maybe there's a property or method on tml3dRenderer or on $scope that you could check to determine when it's finished updating everything, and use that to hide your spinner?