Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Investigate "wait" block to avoid busy-waiting #213

Open
towerofnix opened this issue Jul 16, 2024 · 3 comments
Open

Investigate "wait" block to avoid busy-waiting #213

towerofnix opened this issue Jul 16, 2024 · 3 comments

Comments

@towerofnix
Copy link
Member

towerofnix commented Jul 16, 2024

Following #212, the current implementation for Sprite.wait will busy-wait if no other active threads are requesting a screen refresh.

Our Sprite.wait is (loosely?) modeled after scratch-vm: wait, stack timer, Timer.

If it's possible to implement "wait" in terms of a promise, this would avoid busy-waiting. However, we obviously need to retain behavior semantics, i.e. not break any existing behavior.

I don't know if there have been any previous efforts or discussion, particularly in scratch-vm, to implement "wait" in terms of a promise (and thus consideration of compatibility concerns). We did a cursory look for pull requests and didn't spot anything, but it might be worth a closer look!

@adroitwhiz
Copy link
Collaborator

I believe it was previously implemented as a promise, but changed for compatibility reasons. The "say/think for () secs" block should probably be changed to use a timer as well, but 3.0 currently doesn't.

@towerofnix
Copy link
Member Author

Thanks! See scratchfoundation/scratch-vm#904 (comment) in particular (this comment predates the fix linked above, which basically implements that proposal, just not for say/think).

In any event, "wait" in 3.0 is now in terms of the custom nowObj which gets the runtime's currentmsecs. It is updated at the start of each frame.

If dating back to review scratch-flash behavior, scratchfoundation/scratch-flash#1396 is possibly of interest. There is some further discussion and issue-linking in scratchfoundation/scratch-vm#2138, more to do with run w/o screen refresh than timing behavior in particular.

@towerofnix
Copy link
Member Author

I guess the problem is that the only way to wait a precise amount of time in JavaScript is to, well, busy-wait that amount of time. If you're right that "wait" only busy-waits #212 (comment)

in the absence of any redraw requests

(which makes sense to us—after all at this point Scratch is deliberately waiting til the next frame), then this is precisely an issue when the next execution could be at exactly the specified delay time.

If there's no way to get around it then that's probably that, but it's irritating. Not a serious issue in most projects (which always have stuff moving and updating the screen), but still.

This answer on Stack Overflow is a good answer as of 2014: https://stackoverflow.com/a/21117513/ — and the situation doesn't seem to have changed much, except that setImmediate whent nowhere. Particularly this point:

If you are using setTimeout() on a slower cadence, e.g. once every 300 milliseconds, you could use a solution similar to what user1213320 suggests, where you monitor how long it was from the last timestamp your timer ran and compensate for any delay. One improvement is that you could use the new High Resolution Time interface (aka window.performance.now()) instead of Date.now() to get greater-than-millisecond resolution for the current time.

Also room to look at tock, mainly developed 2014-2015. And a 2010 sitepoint article that inspired/directed tock as well as user1213320's linked answer. Would be nice to find any more recent resources about this problem, still.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants