- Notifications
You must be signed in to change notification settings - Fork1.5k
Deep Dive: Our workers' based synchronous stack#2317
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Have you ever wondered how is it possible that we don't block the main thread (the visited page) while executing remote code that can synchronously read or write anywindow reference? ... well, you are about to find it out, at least on a high level 👍 Worker, Proxy, SharedArrayBuffer & AtomicsThese are the ingredients to make it all happenand the reason for intensive UI tasks, things might feel not as fast as it is when everything just works on the main thread. The current issue with the latest approach though, is that if your code has a The solution to all this is to useworkers, which operate in a separate thread, being that ahyper one or a whole differentCPU core. The roundtrip's TangoIn a worker, we type, as example,
At the end of this convoluted orchestration we'll have thatstring value representing the current location Well, somehow ... yes, but this dance is basically the samePyodide orMicroPython or anyFFI usually does: things are mapped bi-directionally, hooks in theGarbage Collector are created to avoid caching too heavily all possible references, nothing is usually strongly referenced because these programming languages arestrongly dynamic.
That's a lovely question and the simple answer is that we don't really knowahead of time what users are asking for, we can only guarantee that whatever they have asked provided a meaningful, and as fast as it can be, result. Our polyfills' roleTheSharedArrayBuffer primitive has, unfortunately, historic reasons to not be always available unless special headers, provided by the server or a specialService Worker, are in place, and we orchestrated 2 variants that solve the issue, in a way or another, but both variants add some low to high overhead:
When neither variants are fully available, you can see an error inPyScriptdevtools that states:
This does not mean thatPyScript won't work though, it means that the whole magic provided bySharedArrayBuffer andAtomics.wait cannot practically be used so it's not possible to simulate synchronous code at that point. There is still room for improvements!Nowadays, bothArrayBuffer andSharedArrayBuffer instances cangrow in size overtime, this wasn't true 2.5 years ago when we first sketched this wholeworker/main dance. On top of that, there are better primitives to deal with binary data, such as So let's see how our initial plan/dance can be improved now, keeping the
Done 🥳 ... or better, there is no need anymore to:
In few words, what required 7 steps (ask/serialize/binary/length -> retrieve/binary/deserialze) and 2X theRAM, could instead use 3 steps (ask/binary-serialization -> binary-deserialization), reducing complexity and code bloat too, while improving performance by quite some margin. An extra detail ...I need to figure out if using aSharedWorker to create auniqueSharedArrayBuffer that can be used across allmain and theirworkers would work, which goal is to have predictable amount ofRAM needed to orchestrate one to dozens tabs runningPyScript with one to many workers ... that requires alsoWeb Lock API but if it can be done forSQLite I believe it could be done for our project too ... still surfing the edge of modern APIs but hey, we just want the best by all means 😇 We are close but not there yetIf you have followed recent community calls, you are probably bored by me demoing and benchmarking all the things but here an update of our current state:
Are there unknowns?At the logical level, I expect performance to improve that's a natural consequence of removing intermediate steps and reduce by 2 the time it takes to ask and retrieve databut, on the other hand, I cannot measure concretely improvementsuntil this has been done ... I mean, I could hack something around but that won't still provide real-world improvements so maybe I should not focus on that. Last, but not least, it's unclear if/how I canpolyfill this new stack insabayon too but I also expect that dance to be even faster because it won't need more than a single and synchronousXMLHttpRequest to retrieve data, as opposite of ConclusionI am very glad I've managed to tackle all performance issues that were either hidden in implementations (current serializer we use at the moment) or logic (not updated usage of most modern APIs) to actually being able to "draw" on the board what is the current goal and I hope everything will work as planned and that it won't take too long to have a release that showcases performance are finally reasonable enough to stop using themain thread so please follow this space to know further progresses and don't be afraid to ask anything you'd like to ask about these topics 👋 |
BetaWas this translation helpful?Give feedback.