Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
fabiofavale
Visitor

Scene Graph performance degradation storing object models

Hi at all,
i have a problem about performance in a channel if i cache object models during the navigation (requiring listings of items of different sections). To avoid to require every time a json to populate models in a section, i fill data models (associative array object with data and functions) and i store them in a catalog of items. When i need to visualize the contents i read the data models and i pass the data reading the fields i need and pass them to scene graph components through a field "assocarray". 

The problem is when items reach an amount over 1000 the UI experience degrades becoming laggy and slow during animations (some times the box reboots). The main scene of the channel imports a serie of scripts of utilities, script of the screens (controllers) and singletons which stores data models so, all the screens (component container in the scene) have visibilites in their script of these utilities and singletons to access and fill content data of the relative interface.

The channel is a new version SDK2.0 of a channel developped in SDK1.0 and there storing the same amount of items there are no performance issues. 

There is a different limit of memory between Scene Graph and SDK1.0? There is a particular method to manage the memory? Data model are associative array, how they can interfere with Scene Graph? The amount of memory allocated is about the same in SDK1.0 version and SDK2.0 but in SDK2.0 channel slows down. If i put a big amount of data in the main thread to saturate memory channel continues to run fastly, if the data are stored in the scene node, the channel slows down.
What can i do to solve this problem? There is a method to communicate with main thread?
0 Kudos
11 REPLIES 11
RokuNB
Roku Guru

Re: Scene Graph performance degradation storing object models

My guess is that your app slows down because of the deep-copy that happens every time you access (get or set) a field value. When you do `myVar = myNode.myField`, that marshals/unmarshals the structure underneath. Same thing the other way, `myNode.myField = myVar`. Same thing if you do `... = myNode.myField.subAA[7]` - don't you imagine because you specified a minimal substructure, that the whole myNode.myField does not get copied first - it does, then the field is accessed and then the copy is disposed.

How to address that? Minimize as much as possible the access to node fields that are expensive to copy. Or as i call it, "minimize the dotting". You need that big structure in multiple places of your function? - then set a local variable to that in the beginning of the function.
0 Kudos
fabiofavale
Visitor

Re: Scene Graph performance degradation storing object models

"RokuNB" wrote:
My guess is that your app slows down because of the deep-copy that happens every time you access (get or set) a field value. When you do `myVar = myNode.myField`, that marshals/unmarshals the structure underneath. Same thing the other way, `myNode.myField = myVar`. Same thing if you do `... = myNode.myField.subAA[7]` - don't you imagine because you specified a minimal substructure, that the whole myNode.myField does not get copied first - it does, then the field is accessed and then the copy is disposed.

How to address that? Minimize as much as possible the access to node fields that are expensive to copy. Or as i call it, "minimize the dotting". You need that big structure in multiple places of your function? - then set a local variable to that in the beginning of the function.

Thanks to reply, the big amount of data (the catalog of items (AA with data and functions )) is not stored in a field, but in "m" context of the main node (extends scene), the catalog is a singleton and importing all brs in the context of main scene, we assure to have visibilities in all screen's script controllers. Importing singleton brs in the main scene, we assure when we call getCatalog() the array is defined in m context (if m.catalog=invalid :create:else:return m.catalog) so when we access to singleton in the screen controllers we don't pass through a node field with big amount of data, then when we take the interested items (not all catalog but a little part of it) we pass data in the setmodel field of components to visualize the informations.  
We have done an experiment, if we define with a for an array m.catalog with 500000 elements of {description:"a lorem ipsus...long string"} in the m context of main node scene, the box reboots on app's loading, if we use 10000 element the app runs slowly from the beginning (without navigation). if we define the array of 500000 elements in the m context of main thread the app runs fastly without problem at the start. 
So m context of a node is different of m context in the main thread by perfomance point of view? The memory occupied seen by "free" command on 8080 port, is more saturated with 500000 elements on main thread (obviously) but the app runs fastly, with 10000 elments in the m context of node memory is less saturated but the app runs slowly, so memory appears is not the problem but a more computational related problem. 
0 Kudos
RokuNB
Roku Guru

Re: Scene Graph performance degradation storing object models

"fabiofavale" wrote:
So m context of a node is different of m context in the main thread by perfomance point of view? The memory occupied seen by "free" command on 8080 port, is more saturated with 500000 elements on main thread (obviously) but the app runs fastly, with 10000 elments in the m context of node memory is less saturated but the app runs slowly, so memory appears is not the problem but a more computational related problem. 

It's hard for me to follow - can you write/show some minimal code that demonstrates that? Does not have to do anything meaningful visually - but to show what you do and how you times in both cases.
0 Kudos
fabiofavale
Visitor

Re: Scene Graph performance degradation storing object models

"RokuNB" wrote:
"fabiofavale" wrote:
So m context of a node is different of m context in the main thread by perfomance point of view? The memory occupied seen by "free" command on 8080 port, is more saturated with 500000 elements on main thread (obviously) but the app runs fastly, with 10000 elments in the m context of node memory is less saturated but the app runs slowly, so memory appears is not the problem but a more computational related problem. 

It's hard for me to follow - can you write/show some minimal code that demonstrates that? Does not have to do anything meaningful visually - but to show what you do and how you times in both cases.


<?xml version="1.0" encoding="utf-8"?>

<component name="Main" extends="AbstractScene">

<interface>

</interface>

<!-- Application Main Script -->
<script type="text/brightscript" uri="pkg:/components/application/Main.brs" />
</component>


Main.brs
function init() as Void
  m.catalog=[]
  for i=0 to 10000
      m.catalog.push({description:"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,"})
  end for
end function

With this code the app runs slowly at beginning, and if change 10000 with 500000 the box reboots

If i write the loop in the main thread (main from which i create roSGScreen, Scene, etc) the app runs smoothly:

Library "v30/bslCore.brs"
sub Main(args as Dynamic)
    
m.catalog=[]
   for i=0 to 10000
           m.catalog.push({description:"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis disparturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,"})
    end for
  
   runSceneGraphApplication(args,"Main")  

end sub
0 Kudos
Veeta
Visitor

Re: Scene Graph performance degradation storing object models

Here's my analysis based on my experience so far with Scene Graph threads.  Perhaps RokuNB can verify.

The two threads, main vs. Scene, have very different execution models, even though they both run a brightscript code.


  • Main thread enters the Brightscript VM and control stays there for the duration of the app running

  • Scene thread runs Brightscript functions in response to events such as user input, timers, fields written by other threads... then it exits the VM to run other non-Brightscript code handling user input and screen drawing.

So your test of building big data structures in the Main thread does not affect the real-time drawing and user input handled in the Scene thread.  BUT, when you ask the Scene thread to execute a loop that takes a relatively long time, it has to hold up user input processing and screen drawing during that time.  The 10,000 test shows this delay.  When you try 500,000 items, you most likely hit some hard limit on how long the Brightscript code can run before it assumes something is crashed/hung and it forcefully reboots the machine.  

The solution is to use a different architecture, either building the data structure in the Main thread or a Task thread, then passing it to the Scene thread once it is fully formed.
0 Kudos
RokuNB
Roku Guru

Re: Scene Graph performance degradation storing object models

"Veeta" wrote:
Here's my analysis based on my experience so far with Scene Graph threads.  Perhaps RokuNB can verify.

The explanation sounds right to me. The only thing i am puzzled about is that the player rebooted instead of killing only the app (there is a timeout on hogging the render thread, something within 3-10 secs). What action is being taken might be version dependent though, i did not see note which model and which OS.

But indeed, overall no long-running things should be done on the render thread - regardless if in event handler, init() or what have you - because that's the thread that should be re-painting the screen. For slow operations, use the main() thread and task threads.
0 Kudos
fabiofavale
Visitor

Re: Scene Graph performance degradation storing object models

"Veeta" wrote:
Here's my analysis based on my experience so far with Scene Graph threads.  Perhaps RokuNB can verify.

The two threads, main vs. Scene, have very different execution models, even though they both run a brightscript code.


  • Main thread enters the Brightscript VM and control stays there for the duration of the app running

  • Scene thread runs Brightscript functions in response to events such as user input, timers, fields written by other threads... then it exits the VM to run other non-Brightscript code handling user input and screen drawing.

So your test of building big data structures in the Main thread does not affect the real-time drawing and user input handled in the Scene thread.  BUT, when you ask the Scene thread to execute a loop that takes a relatively long time, it has to hold up user input processing and screen drawing during that time.  The 10,000 test shows this delay.  When you try 500,000 items, you most likely hit some hard limit on how long the Brightscript code can run before it assumes something is crashed/hung and it forcefully reboots the machine.  

The solution is to use a different architecture, either building the data structure in the Main thread or a Task thread, then passing it to the Scene thread once it is fully formed.

The loop is done only one time, at the beginning not repetealy in the app, the example has the scope to demostrate what happen if during navigation i store data in the scene graph render thread or in the main thread. Storing in the render thread the app slows down with increasing size of data stored.
0 Kudos

Re: Scene Graph performance degradation storing object models

"RokuNB" wrote:
"Veeta" wrote:
Here's my analysis based on my experience so far with Scene Graph threads.  Perhaps RokuNB can verify.

The explanation sounds right to me. The only thing i am puzzled about is that the player rebooted instead of killing only the app (there is a timeout on hogging the render thread, something within 3-10 secs). What action is being taken might be version dependent though, i did not see note which model and which OS.

But indeed, overall no long-running things should be done on the render thread - regardless if in event handler, init() or what have you - because that's the thread that should be re-painting the screen. For slow operations, use the main() thread and task threads.

Hi RokuNB. You seem surprised that the player would reboot. In development I have my box reboot all the time. The most sure fire way to do this is pass RowList or MarkupGrid and empty content node but there are plenty of other ways to do this as well. The most frustrating part is unless you recognize it right away it's hard to figure out what caused the reboot because no message is ever logged about what caused the box to reboot
0 Kudos
RokuNB
Roku Guru

Re: Scene Graph performance degradation storing object models

"bleightyturner" wrote:
Hi RokuNB. You seem surprised that the player would reboot. In development I have my box reboot all the time. The most sure fire way to do this is pass RowList or MarkupGrid and empty content node but there are plenty of other ways to do this as well. The most frustrating part is unless you recognize it right away it's hard to figure out what caused the reboot because no message is ever logged about what caused the box to reboot

Can you write a short example that demonstrates this? If it's reliably reproducible, love such bugs because are easier to track and fix.
0 Kudos