5 ms·
Main-Thread-Scheduling
- astoilkov 3y agoThe author here. Just opened HN and saw that my library is on the front page . If you have any questions, I can answer them.
- susi22 3y agoHow does this differ from cooperative multi tasking?
- jerf 3y agoIf I'm reading this correctly, this is a library for use within a browser, in which case the answer is that this makes it easier to live within the constraints of the browser, which has arguably the strangest "multitasking" support anywhere, what with all the constraints it had to satisfy to be added in to an architecture already 15 years old at that point.
- astoilkov 3y agoYeah, that sums it up. The library tries to use the single thread the browser UI is running on and just not freeze it.
- rictic 3y agoHave you benchmarked the overhead of awaiting? I believe that in doing so you yield to the microtask queue and then your function has to be scheduled and run again. You could compare await yieldOrContinue('user-visible'); doSomeWork(); against if (isTimeToYield('user-visible')) { await yieldControl('user-visible'); } doSomeWork(); A few years back when I measured it on a fast laptop the cost was ~1µs to do `await 0;`
- astoilkov 3y agoI haven't. I should do that. Many people are talking about this and this makes me think I should measure and talk about it in the readme. Thanks!
- dnmllr_ 3y agoHi, forgive me if I missed it, I just briefly browsed the repo. Does the library itself handle cancellation, or would user code be responsible for that?
- astoilkov 3y agoThis is on my list. I want to provide a `signal` property to enable easier and more efficient cancellation.
- foolswisdom 3y agoHow is this able to pause work, given that the work is already executing on the main thread (and I assume you don't need to rewrite your code to explicity give up control at various points)?
- bastawhiz 3y agoYou await the `yieldOrContinue` function. `yieldOrContinue` returns a promise that resolves when your code should resume running. Your work will only be paused at places that you explicitly await the provided functions, so yes, you do need to explicitly give up control.
- astoilkov 3y agoYes, that's it. You choose where to pause/resume work and place the calls to `yieldOrContinue` there.
- cryptonector 3y agoThe only gotcha is that you have to choose wisely. It's not a bad thing though. This is really cooperative multitasking all over again.
- esprehn 3y agoPretty much, which is how browsers work in general with the single thread (ex. The html parser yields after a certain number of tokens or if user input is waiting). React's concurrent mode is the same thing as well.
- deleted 3y ago[deleted]
- bastawhiz 3y agoI really like this. This feels like what the native APIs would look like if Promises existed in the 90s. One thing that might be improved is removing the `Promise.resolve()` that `yieldOrContinue` returns when it is not time to yield. Awaiting non-Promises is totally fine: you just get that value back (the `await` does nothing). Avoiding constructing a resolved promise can help reduce the number of objects that get allocated, especially if you're in a loop doing a lot of work.
- astoilkov 3y agoIt's done — https://github.com/astoilkov/main-thread-scheduling/commit/0bbbb9d93a7408df0c1160eecbcf28e4afe9292c https://github.com/astoilkov/main-thread-scheduling/commit/0.... Thanks. A little thing but a great improvement. I'm now wondering why I did that.
- rixtox 3y agoYou should do some measurement before calling it an improvement. If you read the ECMAScript standard[1] or this blog post from V8[2] about the inner workings of the `await` keyword, you would know even if you `await` a non-Promise value, it would still create a new Promise and put the suspended routine onto the microtask queue. So the change you made won't make a difference. Besides, there is a JavaScript language feature that can give you finer control on routine suspension and resumption, decoupled from any of the microtask or macrotask queue. It's called the generator function. There are some good coroutine libraries based on generator functions, e.g. co.js[3] and redux-saga[4]. You can easily make something similar that can resume the suspended routine according to your scheduling policy that prioritize main thread rendering. [1]: https://tc39.es/ecma262/#sec-promise-executor https://tc39.es/ecma262/#sec-promise-executor [2]: https://v8.dev/blog/fast-async#await-under-the-hood https://v8.dev/blog/fast-async#await-under-the-hood [3]: https://github.com/tj/co https://github.com/tj/co [4]: https://redux-saga.js.org https://redux-saga.js.org
- astoilkov 3y agoYeah, you are right. I reverted the commit. About the generations, do you imagine a function that accepts a generator function and the user uses yield? Something like: ``` mainThreadScheduling(function *(yieldOrContinue) { yield yieldOrContinue; }) ```
- jillesvangurp 3y agoI've done some browser applications using kotlin-js. One of the nice things with kotlin-js is that you can use co-routines. That's a nice upgrade over of promises or even async await in typescript. And you can easily await javascript promises in kotlin (extension function) or deal with javascript code that expects a promise. Co-routines basically gives you structured concurrency, a bit more sane error handling with this, and a few more things. Javascript and typescript are a bit bare bones with this. And of course in a browser, everything is basically happening asynchronously. So, there are a lot of places where co-routines can be useful. And you can just spin up stuff with launch {} as well and have things running in the background. Nice with web sockets for example.
- sroussey 3y agoWhat primitives does kotlin-js use? Promises or generators?
- scrubs 3y agoRepo has a great readme.md. well written
- astoilkov 3y agoThanks!
- bironran 3y agoMight be only my limited understanding but isn't that trying to recreate cooperative multitasking? That was tried, and often failed, for many years in the OS space.
- kevingadd 3y agoSadly in the browser you have no choice but to perform cooperative multitasking, since the execution model prevents the browser from performing preemptive multitasking.
- yencabulator 3y agoThe README says "ensure" quite often for being a cooperative multitasking library that depends on regular `yieldOrContinue` calls.