Boa: Move Realm creation to another thread

Created on 31 May 2020  路  10Comments  路  Source: boa-dev/boa

Realm creation is currently quite slow, and lexing and parsing doesn't start until this is finished. In the screenshot below we can see that Realm::create() runs on the main thread, and blocks everything else until its finished.

I think further optimisations can be done here to:

  • Speed up set_field() which is where most of the time is being spent
  • put the &global env into a Mutax and create each of these objects concurrently

image

I'm also happy to discuss any other ideas or opportunities here

enhancement help wanted optimisation discussion

All 10 comments

Have a few more ideas relating to throwing some of the builtin construction into threads, beyond just Realm::create()

Firstly, in regard to

put the &global env into a Mutax and create each of these objects concurrently

To prevent the overhead of accessing the global object via a Mutex during execution of JS code, it might be better to have the threads that create the builtins instead send the object they create to the main thread via a channel, so the main thread will be the only thread that mutates the global env.

This would also require updating every one of the init functions to not modify the global env - but this could be tricky, considering global is interior-mutated and the main thread writing to it may run in line with another thread having a read-only borrow done on it (such as to access an object for a prototype) which would cause a panic.

Maybe to solve this, the worker threads can send construct them concurrently, but the main thread will add them only after they are all finished.

But, this also presents a problem: some builtins need certain objects to exist during their own construction. For example, constructors that require the Function global object as their prototype. Maybe the solution to this would be to do required objects first, then the other ones in parallel afterwards.


Next, if these objects are constructed concurrently, a further optimization might be to have a thread initialize groups of them so each thread has similar amounts of work.

For example, one thread each for array, math, string because these are pretty big.
One thread to do all of bigint, boolean, etc. because each of these are pretty small, so it can accomplish all of them in (theoretically) the same time one thread will accomplish array.

Might be an optimization of an optimization, and it would require testing and benchmarking at each step.

I think it would be good to have the simple solution first, 1 thread per builtin, and try to see how that measures up to grouping up a few of them, since thread construction isn't free.

At some point, execution could also be done in streaming, in which case, the realm would need to be ready when the execution starts (which would call the parser streamer).

I've linked https://github.com/boa-dev/boa/pull/419 with this because the optimisations in that should bring the realm creation time down significantly.

Once that's done I will do another measure to see the impact
Edit: I think the PR being done will close this issue so removed link but reference remains

I went back to the May 31st commit to see how the code looked back then and since then there was the Value Refactor by @HalidOdat https://github.com/boa-dev/boa/pull/498 which sped up objects and consequently field access by a lot.

Looking at https://boa-dev.github.io/boa/dev/bench/ it seems Realm Creation has become considerably faster than it used to be, keeping this up in case in the future we want to introduce multi-threading once the builtins are more developed?

The thing is that currently, we first tokenize + parse the whole program, and then we start creating the Realm. This creation is faster, but it could be parallelized with the lexing + parsing. We need it even if we fail to lex/parse, since we need to generate a Syntax Error.

The problem with trying to implement a parallel initialization for Realm is that a lot of them depend on each other, even if that was not the case when we create a new Gc<> it is stored in a thread_local so Gc<> is not Sync or Send so we cant pass them through threads. we might be able to initialize the Realm in the main thread while we parse/lex the code.

Parsing and lexing should be independent of realm setup as neither of those tasks require use of the Gc, it鈥檚 only when you鈥檙e ready to execute it becomes a problem.

The thing is that currently, we first tokenize + parse the whole program, and then we start creating the Realm.

Has this changed?
Last I checked realm setup happens first then parsing starts once鈥檚 it鈥檚 built. https://boa-dev.github.io/2020/07/03/boa-release-09.html

Has this changed?
Last I checked realm setup happens first then parsing starts once鈥檚 it鈥檚 built. https://boa-dev.github.io/2020/07/03/boa-release-09.html

Not that I'm aware of, I might have mixed up the order, but the thing is that one waits for the other.

I wonder if for now we can change the order and do the parsing before realm creation.
That way if there's an early error we don't need to bother building the realm.

image

We still need the realm to create a SyntaxError if the parsing goes wrong, right?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

IovoslavIovchev picture IovoslavIovchev  路  4Comments

Razican picture Razican  路  5Comments

HalidOdat picture HalidOdat  路  3Comments

Razican picture Razican  路  4Comments

attliaLin picture attliaLin  路  3Comments