Breakout session on Threads
This breakout session was part of the Workshop on Web games. Minutes taken by Dominique Hazaël-Massieux.
David: got some ideas shared by
email after our discussion yesterday
... initially, I thought that Web workers are painful to
start
... the serialization/deserialization needed to communicate
among workers is also costly when you need to constantly share
info across threads
... for instance, synchronizing scene graphs across workers is
costly
... SharedArrayBuffer is useful but not enough
... someone shared the idea of a Task concept which captures
and freezes a context
... the task starts on a new thread and has read-only access to
the starting context
... this would work very well for my scene graph case, physics,
or collision detection
... more difficult for particles, but still probably
usable
... this would solve quite a few problems
@@@: with a readonly context, you probably need to have very light threads because you would likely need to start many of them rapidly for a short time
David: there is a similar
approach in C# with a pool of threads that get recycled
... very cheap to start
Myles: the worker in this model
would see a read-only view of the model
... what about the main thread then?
Rafael: it would have to be read-only
David: I think the main thread should be kept out of the equation to simplify the model
Myles: what is the status of rAF in workers?
David: it works
... I have rAF in a worker, OffscreenCanvas in a worker, soon
user input
... the last thing I need is to be able to separate the work in
that thread
Myles: OffscreenCanvas still needs
to hands off its results to the main thread
... this could be done here as well
@@@: you will still need some form of blocking for read-only state management, so we need to keep this thread-spawning off the main thread
david: that's what the proposal is indeed
Navid: I believe there is work
under way to use OffscreenCanvas without interfering with the
main thread at all
... workers don't have access to the DOM currently; there is a
project to enable DOM-splitting with some defined CSS property
to indicate that a part of the DOM needs to be composited
differently
... similar to cross- vs same-origin iframes
... this would allow to hand off part of the DOM to a specific
worker
... this would enable to render different part of the pages at
different frame rates
Ricardo: OffscreenCanvas has indeed that feature with "transferControl"
David: the constraint right now
is how workers get started
... to start a worker, I have to re-import all my libraries in
a worker
... it would be great to be able to spawn a worker with the
same set of loaded libraries
... (not mentioning that all of these need to be managed as
different files, which isn't good wrt webpack-ing)
Myles: let's say there was way to
tell this function runs into a separate worker
... how does this work with the global scope?
Luke: Jonas Sicking looked into
this a few years ago; it's pretty difficult, would need to
convince quite a few people
... we had a separate project called parallel JS that
investigated this, was presented to TC39 but not well received
and created challenges in implementations
... the closest thing was "FunctionPromise" (?)
... which made it easy to create cheap-to-instantiate
string-defined functions that could be transfered to a
worker
David: I could see that working, but that leaves the problem of imported scripts - we would need an API to include these in the pack
@@@: how would that work with the various optimization processes?
Luke: there would be opportunities for sharing machine code across these threads
David: the lack of multithreading in JS is unique in the world of programming languages
Myles: one fundamental difference is that this prevents multi-thread race crashes
Ryan: being able to cache pre-compiled or JITed code would be useful for game engines
Andrew: the one hope for that is the cache API with ServiceWorker - cloned copies of responses can make use of pre-JITed code
Dom: is that feature of the Cache API a well-known aspect?
Andrew: not sure - there will
probably be an info box in the spec
... in any case, it won't be a guaranteed behavior
... we would also want to avoid heuristics being abused
Luke: parsed-but-not-instianted code I was alluding to is what WASM provide
Ryan: that's interesting, but will we lose this ability in JS?
David: +1 - let's not make JS a
poor child of the Web
... let's make sure all these new cool features remain
available to JS devs
Dave: from our experience,
running WASM on low-end android is impossible from a
performance perspective
... because the code is too big
Nick_Hulu: embedded devices,
low-end devices don't have access to JIT; it would be great to
be able to parallelize
... threads would be our only way to keep performance in this
constrained environment
Ryan: there are more or more use
cases that don't have JIT
... e.g. in cars
David: I hear consensus on the
user-side - threading is needed
... but I hear lots of frinction from browser devs
Andrew: you mentioned there was 2
separate execution environments which creates deployment
challenges
... do ES6 module help?
... it doesn't solve all the packaging issues
David: the challenge is as a
framework developer, asking my users to deal with that
complexity is something I would prefer avoid
... I also can't tell which modules my users have imported
before I start a new worker
Ryan: I'm curious about this duplicate concept - what would that cover?
David: just the code
@@@: but what about e.g. dynamically generated functions?
Dave: this can be solved by a nice import function
David: but that still creates complexity
Myles: do you have a helper library that deals with this importing? how do you manage it?
David: right now I have to
manually import the scripts, finding the right paths
... I have to create a URL object to manage my workers
Myles: maybe we should start by optimizing your current approach instead of doing a broader redesign
Dave: the issues that were
summarized yesterday: the split file issue is one (but there is
a workaround), shared memory will be helped by
SharedArrayBuffer but doesn't solve the cases where you need
object that get serialized/deserialized
... not sure how your read-only model would help with e.g.
Physics Engine
Luke: a challenge with JS objects
is that they're very complex
... there is a proposal for a TypedObject in JS that may help -
it brings an immutable structure
... part of the idea would be be able to mark them as shareable
- in which case they can only point at shareable objects
... this could help with multi-threading
... this would also help with gc-support in WASM
... TypedObject would be the reflection of gc-objects
Dom: this is in TC 39?
Luke: yes, at Stage 0 (there is an explainer)
Andrew: would it have similar shared semantics as sharedarraybuffer?
Luke: roughly
Ryan: what are structural limitations?
Luke: it has a weak memory model
Rafael: even in a mono thread this would go a long way to help with David's problem
David: it would indeed solve some (but not all) use cases
Dom: in summary?
David: worker initiialization and
scripts imports could be simplified
... TypedObject provide nice opportunities for memory
management for Games
Nick: I liked Luke's idea about cached-JITed code
Luke: see FunctionPromise in TC 39
@@@_King: coming from a C++ background - will emscripten manage this directly?
Luke: WASM takes care of it