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: 
destruk
Binge Watcher

Re: Parsing JSON v XML

As for the task node itself, I use m.downloaddata=m.top.findnode("DownloadData")
I can set the control to "start" and it downloads, then it fills the "content" interface with the downloaded string, and the main scene builds the contentnodes to populate the screen with.
If you are getting the information from m.downloaddata.content to do this, then it is building the nodes in the thread where that line appears.

If however, the content node is using setfield and/or setfields within itself based on the data it downloaded within itself to create the content nodes, then how do you get that data to where you can use it?  Do you say, have a component called rowlist, and you have it m.rowlist.setcontent(m.downloaddata.content) after populating the m.downloaddata.content interface with the contentnode and set to type "node" ?

I can try some more things here as I just changed all the feeds to json and optimized the server for fields that aren't used, etc etc.  Thanks again for your help.
0 Kudos
RokuNB
Roku Guru

Re: Parsing JSON v XML

"destruk" wrote:
RokuNB -
In the channels main.brs, I create a roSGScreen
Next I use CreateScene for my main scenegraph thread.  This is what I think of when I say "Main thread, or render thread" As it is the first screen the app displays. If that isn't the render thread then I don't know what the render thread would be?

Seems we have fundamental misunderstanding here.

This is your main thread - the traditional B/S program from pkg:/source:

 ' ... '
 screen = CreateObject("roSGScreen")
 port = CreateObject("roMessagePort")
 screen.setMessagePort(port)
 ' ... '
 screen.show()

 while(true)
   msg = wait(0, port)
   if type(msg) = "roSGScreenEvent"
     if msg.isScreenClosed() then return
   end if
 end while
 ' ... '

Everything else in your scene, components, tasks - the init() events, keys, observers - is NOT the main thread. Typically all this stuff us in the render thread (completely different from main). And then there are the task threads.
0 Kudos
destruk
Binge Watcher

Re: Parsing JSON v XML

ok, thanks. 🙂
ParseJSON and Parse() works in task threads and it works in the render thread.  It is just as fast to do the parsing in all three places - the main thread (main.brs), my main scene I create with the UI for the user, and the task node threads.  However, the timing problems are apparent when I build contentnodes in the task node.  It is faster in the scene components which are not tasks, than in the task node, and then I haven't been able to populate the screen with the content yet if it's built in the task node.  But I'll experiment some more to try to match what roku wants their code to be doing in channels - it'll take some time.
0 Kudos
destruk
Binge Watcher

Re: Parsing JSON v XML

Running the entire parse, content building, etc in the task thread for 52 items takes 8 seconds.  Populating the main screen worked by putting the content node itself into the task node interface field with it set to type "node" instead of "string", it worked just like you said it should that way - but it's still slow.  In the render thread it takes ~2 seconds.
I'll try changing the feed so it can fully use "setfields" to see if that is faster.  It should be but I won't know how much faster that is until I try it.
0 Kudos
RokuNB
Roku Guru

Re: Parsing JSON v XML

Honestly, i had no idea that parseJSON() and xml.parse() now work in the render thread. I remember they did not work - and the docs don't mention a recent change, so you might be on thin ice using that.

I bet the reason that it is "faster" in that thread is that you are "hogging up" the CPU - while you are running your event handler/observer, the render thread cannot do any re-drawing of the screen.

So you had the wrong type of field and assigning to that was silently failing w/o an error? That is not good, not good at all.

52 items in 8 seconds takes way too long, should be much faster. Are you "overusing" customized components? In other words, can you try using standard nodes (like Node or ContentNode) instead, by just adding the extra fields with say .addFields()? See if that speeds it up, i remember recently seeing complains that extending/subclassing nodes carries big penalty.
0 Kudos
destruk
Binge Watcher

Re: Parsing JSON v XML

hmm... alright.  First, thanks again for being so responsive here RokuNB.
It was a whole lot of work - took hours, to rewrite the php scripts, but now the server is generating everything each content node for each item for each category and screen, for all content requests, named exactly like Roku requires them for each meta-data value.  It generates json responses with the subtitleurls, subtitleconfig, bif files for sd/hd, poster urls, media urls, streamformats, etc - the entire shebang.
This allows the roku client to simply download the feed, execute a parsejson, and then use setfields to grab everything it needs for a contentnode.

I am getting some strange results from the code profiler now.
With the task node doing everything in regards to the content generation from the downloaded feed of 457 items, it takes a total reported time for the entire app of 4.1332
With the render thread doing the content generation and the task node doing the download of the identical feed of 457 items, it takes a total reported time for the entire app of 4.5474
Then I retested them again and the renderthread version is slightly faster than the task node thread.
The task node version is a lot more consistent on times over multiple runs, and it's real close in the profiler, so I would ?guess? using the task node in this scenario is the preferred, more stable way to do it?  At least with a task node it won't do an execution timeout so it ought to be able to run the 5000+ item content generation without an issue, lol... I'll time that next.
0 Kudos
destruk
Binge Watcher

Re: Parsing JSON v XML

wow... alright.
So now if it's done in the render thread it crashes after 3 seconds as it's supposed to, but it managed to parse and create nodes for 3500 individual content items before crashing out (with the new predefined feed and setfields).
For the task node thread it successfully made content nodes for all 4891 items I told it to, without crashing.
Profiler for render was totaltime 7.1833 (487 items created per profiler unit)
Profiler for task was totaltime 8.007 (600 items per profiler unit)
So the task node is better overall and appears to be faster overall too. 🙂

What have I concluded?
Setting fields individually eats up a lot of cpu, especially if you need to modify them from what the feed is providing.  If they are pre-formed and named correctly and setfields is used then that is the best way to go.
Thanks again for your help with this.
0 Kudos
destruk
Binge Watcher

Re: Parsing JSON v XML

Amazing...just for kicks I compared the old pre-scenegraph code using the standard parsing routines and screens and it took 13 seconds realtime (because the profiler doesn't appear to work for pre-scenegraph?) - and the current code takes 8 seconds.  So I'm tired enough now to sleep. 🙂
0 Kudos
RokuNB
Roku Guru

Re: Parsing JSON v XML

"destruk" wrote:
Then I retested them again and the renderthread version is slightly faster than the task node thread.
The task node version is a lot more consistent on times over multiple runs, and it's real close in the profiler, so I would ?guess? using the task node in this scenario is the preferred, more stable way to do it?  At least with a task node it won't do an execution timeout so it ought to be able to run the 5000+ item content generation without an issue, lol... I'll time that next.

You shouldn't over-rely on the newly introduced profiler tool - first, it's brand new so some things may need polishing yet (it's the nature of software). Second, the act of measuring introduced delays and affects the results. The point of a profiler is to tell you where in your code are the hot spots you need to resolve. To measure overall run time only though, you could easily use roTimeSpan - with profiling off. I would be more confortable trusting roTimeSpan w/o quantization for overall run times.

And yes, for all long-running code i wholeheartedly recommend tasks. To parody the google guys, "Tasks where we can, Render where we must"
0 Kudos