Check me on this gang. The following
msg = wait(1, msgport)
is coming in at around 15 milliseconds. Now, for a 30 fps render loop I only have a 33.33 millisecond window to operate in. The render loop requires getting user input. Now, on a Roku 1 this comes in at 1 ms (still too long in my opinion, but I can probably live with it). On the roku 2 boxes they have “hooked” the wait/sleep routines for other purposes, or they otherwise take longer, such that it is using almost 50% of my available time… not to render but to check for remote input. I still have to render when done waiting for input.
Maybe it’s me. Can someone check on this and confirm? It makes a Roku 2 render loop almost impossible in BrightScript if I’m correct.
Maybe they could check if they are “in game mode” and not take so long with whatever it is doing on a Roku 2 vs a Roku 1???
Pardon my post if this is already a known issue…
Thanks in advance for the feedback.
MW
EDIT: I should note that the wait is on a ro UniversalControlEvent for an roScreen.
I can confirm that I’m getting ~15ms on the first wait, then 10ms consistently after that. The same if I use a Sleep(1) instead. On the Roku 1, I’m getting 1 ms as expected.
“MazeWizzard” wrote:
Now, on a Roku 1 this comes in at 1 ms (still too long in my opinion, but I can probably live with it)
I don’t understand this comment. You’re telling it to wait 1 ms… why would you think it actually taking 1 ms would be too long?
It only means that if there is no pending input, why wait a whole millisecond (we’ve been down that road before with the wait thing in several other posts… but 0 means wait forever, and there is no -1 or other way to return immediately). Its not that I didn’t expect 1 ms, just annoyed that I have to wait 1 ms rather than having an option of returning immediately if no input is available.
Anyway.. that’s a distraction… an offhand side-comment that I should have omitted. The point is “what is it showing for others on a roku 2… 15 ms ish?”
However…Thank you for the confirmation. 15 then 10 ms. OK. Confirmed.
you could perhaps optimize a bit by only checking for input every x milliseconds or so:
if timer.totalmilliseconds() > 100 then
msg=wait(1,port)
timer.mark()
end if
Meanwhile, I’ve verified the issue and filed a bug report.
Thanks RokuJoel. IDK what it is… hope there’s a “smoother” solution to whatever it is doing.
I had considered checking for input every other loop, or every 3rd, or whatever. That would average the negative impact out a bit. I still need to check the R2’s timing on the AnimationTick() and Draw()/DrawAll() routines… maybe they are faster on an R2 and it will all work out. I still have options for dropping fps target down a bit too I guess.
I agree that its either a “bug” or an “undocumented feature difference” (?lol?) between the two boxes.
Anyway.. thanks for taking the time and for the support.
Assuming I am understanding your use case correctly, you don’t need to call wait() at all. Just do this:
msg = port.GetMessage()
if type(msg) = “roUniversalControlEvent” then
end if
No waiting required, and you’re not subject to the bug.
You guys rock. It worked.
I thought you had to bind it to the roScreen (via SetPort() ) and go through that via a wait. Obviously not. Good to know. Missed the GetMessage() part of the port object. Many of the examples have Wait() in them, so that’s what I thought you did! :? :oops: Guess I should check out roMessagePort more closely…
I can always create my own self-timed sleep() if needed at all.
Thanks!
Rather than using sleep to control event timing, as sleep() and wait() suffer from the same issue, consider using several roTimeSpan objects to trigger events at a specific duration:
timer=createobject("rotimespan")
timer.mark()
then:
if timer.totalmilliseconds() > 25 then
timer.mark()
executemytimedfunction()
end if
or, reset the timer after executing your event:
if timer.totalmilliseconds() > 25 then
executemytimedfunction()
timer.mark()
end if
Depending on if you want, for example 25 ms between events, or 25ms inclusive of event execution time.
Very useful for updating multiple objects on the screen at different intervals.
Would using a goto work?
ie from the deviantart sample - minorly modified
collectinput:
msg = port.GetMessage()
If Type(msg)=“roPosterScreenEvent”
If msg.isListSelected()
end if
end if
goto collectinput
To basically remove any reliance on sleep or wait specific commands. Since it’s a poster screen, the up and home and back buttons are hardcoded and handled already so the box shouldn’t die. ? Or you could use this for a roImageCanvas handling each specific button within the goto loop - possibly with a timer as suggested to draw the screen at set intervals faster than the enforced 15ms/10ms delay?
Personally though, I would really prefer if it was changed back to closer match the roku1’s timing if at all possible.
“TheEndless” wrote:
“RokuJoel” wrote:
Rather than using sleep to control event timing, as sleep() and wait() suffer from the same issue, consider using several roTimeSpan objects to trigger events at a specific duration
Assuming you mean inside a while loop (can’t think of any other way to track it), without a sleep in there, that sounds like a really good way to lock up the box, particularly if you’re not listening for any events. But, if you add wait in there to catch any events (and to give the processor some breathing room), you’re right back to square one.
That’s how I was thinking about it when I created this post. However, now I’m guessing that Wait() doesn’t really do anything (as far as the message is concerned) other than wait on a message coming in.
So … to rephrase… you don’t need wait() to let the box process messages. You can just check the port directly without calling wait(). That processes the message, no waiting required.
As to using roTimeSpan objects… I use em for all sorts of stuff and even have a finite-state-maching pseudo-BG process. I don’t use sleep() inside render loops either (or anywhere else other than in the code profiler calibaration routine…but that’s changing too). But hey, it’s an interesting discussion. A Sleep() routine is easy to create yourself if you want one. Joel is correct that you may as well do something while waiting.
The gang at Roku should verify what Wait() is doing…and if using it is somehow required once in a while. However…
while <looping-condition>
msg = msgport.GetMessage()
if type(msg) = ......
<process message>
end if
<other loop stuffis>
end while
Is a no-wait no-lockup way to do it, or seems to be so far. Like KevinG said above.
So… Kevin and Joel are correct that Wait() and Sleep() are probably, umm…, less than necessary. (EDIT: They didn’t actually say that.. I don’t want to mis-quote…so read above…looks like we have options). However the sample code is full of wait() s. lol.
I could always replace them for now with something like this (I haven’t checked this code at all … just trying to communicate an idea here)
Function MyWait(ms as Integer, ThePort as Object) as Object
t = CreateObject("roTimeSpan")
result = ThePort.GetMessage()
while ms >= 0 and result = invalid and (t.TotalMilliseconds() < ms or ms = 0)
result = ThePort.GetMessage()
end while
return result
End Function
Sub MySleep(ms as Integer)
t = CreateObject("roTimeSpan")
while t.TotalMilliseconds() < ms and ms > 0
end while
End Sub
However, the question remains… why even use Wait() or sleep()? There may be a reason… but I don’t know what it is (since I don’t have their code… can’t see the internals). Maybe it does give the processor a break… or give the IR/RF sensors time. Or something else entirely. I guess the question becomes… What do we lose? What’s it doing now that it won’t do if we omit Wait()?
“TheEndless” wrote:
that sounds like a really good way to lock up the box
I haven’t seen while loops locking the box, even empty ones, I use them all the time when testing, instead of using stop, to prevent test code from exiting when it completes. Since he’ll be checking the message port, just without a wait(), it should be exitable if he puts in a handler for remote keypress.
All this should be less relevant when the bug is fixed in the firmware.
“destruk” wrote:
Would using a goto work?
Don’t use Goto. (except, perhaps, as an emergency patch for a bug you haven’t tracked down yet)
http://www.techrepublic.com/blog/geekend/webcomic-why-you-should-never-use-the-goto-command/782
Joel
That’s like saying Globals will destroy your program, and yet you include “m” - for that purpose.
If you say don’t use it, you can remove it from brightscript. I figured it was included for a reason. I thought the thread was about not using Wait and Sleep.
heh
If there is a solid undeniable reason to not use GOTO, then I suggest it be documented why, as well as removing it from the sample applications.
LOL @ the comic. I just picked up my first Arduino and was reading the reference docs last night and came across the goto entry:
http://www.arduino.cc/en/Reference/Goto
The use of goto is discouraged in C programming, and some authors of C programming books claim that the goto statement is never necessary, but used judiciously, it can simplify certain programs. The reason that many programmers frown upon the use of goto is that with the unrestrained use of goto statements, it is easy to create a program with undefined program flow, which can never be debugged.
With that said, there are instances where a goto statement can come in handy, and simplify coding. One of these situations is to break out of deeply nested for loops, or if logic blocks, on a certain condition.
for(byte r = 0; r < 255; r++){
for(byte g = 255; g > -1; g--){
for(byte b = 0; b < 255; b++){
if (analogRead(0) > 250){ goto bailout;}
// more statements ...
}
}
}
bailout:
I should have qualified that by saying it is my own personal bias as far as Goto is concerned, I was trying to inject some humor, perhaps a bad idea. Yes, goto is included in Brightscript and probably will stay in the SDK, and as long as your code works, I don’t think we have any issue with you using goto in your code.
“RokuJoel” wrote:
“TheEndless” wrote:
that sounds like a really good way to lock up the box
I haven’t seen while loops locking the box, even empty ones, I use them all the time when testing, instead of using stop, to prevent test code from exiting when it completes. Since he’ll be checking the message port, just without a wait(), it should be exitable if he puts in a handler for remote keypress.
It’s not documented in the SDK documentation at all, beyond its existence, and I’ve never used it, so I could be wrong, but I assumed that GetMessage() would block until a message arrived (essentially equivalent to Wait(0, messagePort)). Is that not the case?
As for not using Wait loops, that seems to contradict all of the documentation and sample apps, as “Event Loops” are explicitly documented as the way to process messages, and as noted above, GetMessage() isn’t documented at all. That’s somewhat confusing. Should we be using GetMessage() instead of Wait()??
“MazeWizzard” wrote:
However, the question remains… why even use Wait() or sleep()? There may be a reason… but I don’t know what it is (since I don’t have their code… can’t see the internals). Maybe it does give the processor a break… or give the IR/RF sensors time. Or something else entirely. I guess the question becomes… What do we lose? What’s it doing now that it won’t do if we omit Wait()?
If you know you’re only doing work at a specific interval, then it’s wasteful to lock a thread in a continuous loop and eat up CPU cycles that other threads (i.e., the UI thread and the screensaver thread) could benefit from using. A Wait will make the thread idle (freeing up resources) until it has work to do and a Sleep allows you to force a specific idle time. Whereas a while loop keeps that thread active and consuming resources 100% of the time, even if it only has to do work 1% of the time.
No, it is not documented as far as I can tell, it is a workaround one of our engineers suggested, which appears to work well.
Since Brightscript is not multi-threaded, I don’t think you need to worry about thread locking at this point. What I was suggesting was using timespan based triggers to create a psuedo-multitasking experience when writing games and other heavily time-dependent functions (for example, I used this for the Holiday Channel ScreenSaver’s various moving graphics). Freeing up 10-20ms by eliminating the wait() on the Roku2 platform, and even the 1-2 ms on the “Classic” Roku platform is significant from a game developer perspective where every millisecond counts.
sub main()
screen=createobject("roScreen")
port=screen.getport()
timer=createobject("rotimespan")
while true
timer.mark()
msg=port.getmessage()
?"time: ";timer.totalmilliseconds()
?"message: ";msg
end while
end sub
As far as I can tell, it does not block at all, and is generally < 1 ms to check the port.
Well, I agree philosophically with TheEndless about playing nice in a multi-tasking environment and not chewing up resources needlessly. It doesn’t appear to block with my tests either. However, with my particular use-case, since I was dealing with a render loop… lol… Joel and Kevin are correct as far as the current solution goes (at least until the situation is clarified and/or resolved).
“RokuJoel” wrote:
Thanks. Yeah, that’s why I created this post/thread. The “direct poll” is working. I still don’t know what Wait() is doing for those 10-15 ms and if I’m losing anything by “hogging” the cpu cycles and avoiding the “issue”. There’s probably more than some context-switch going on here. But that’s up to the Roku gang to inform me about if I need to do something else; like if the box needs for me to call some other routine every once in a while. Linux will preempt the task at regular intervals anyway. If you’re actually waiting for the user… rather than checking for possible input in a render loop… use Wait().
As to pseudo multi-tasking… I already do that (not timer triggered exactly but … it’s more than I want to get into here in this post).
Goto smoto. lol. I try to never use them except in rare cases like mentioned above. Funny tho.. on some processors everything gets compiled down to a goto anyway. Funny discussion. Not worried about it tho.
“TheEndless” wrote:
OK. Lol. I wouldn’t bet against you on that… sounds like a reasonable guess.
Next question then… what’s sleep() doing for those extra 9 ms. And don’t say “calling wait()” (jk) lol.
I’ve tried to say it a couple of ways.. but … the question is… Is it doing something necessary?.. something that I would be skipping if I didn’t use sleep() or wait(). That could cause trouble.
Maybe it’s my imagination, but I thought there was a flirtation with having Wait() return immediately a few revs back and it didn’t work. So.. maybe something else has to happen during wait()/sleep() internally that we don’t know about. Or maybe it’s unrelated… if it happened at all (I could be thinking of another platform entirely…). They say the mind starts going about middle age…
