Multi Web Worker Example
Introduction
This example is not intended for beginners. I will assume that you have understood the Single Web Worker Example. If you are unsure how IFC works, then check out: What is IFC?
Background
A single Web Worker
will not be enough for a large file, say > 20MB.
Yes, the Web Worker
runs in the background but its synchronous code.
We can use multiple
Web Workers build asynchronous code.
Check out: Asynchronous Vs Synchronous Programming
One might call this approach multithreading
or parallelizing
.
I really don't want to go into technicalities right now... but for the sake of simplicity.
Let's call this approach:
Multithreading
This might be a new concept if you only worked with web development. If you have a background with C, Java, Python, etc. than this will be easier to understand.
Anyways, let's continue!
Prerequisites
A modern Web Browser
An understanding what multithreading is
Patience you must have, my young Padawan
Work with modern browsers
In order to do multithreading
we need to do one thing:
We need to spawn additional, descendant dedicated Web Workers
Most modern browser should be able to do this... but not Safari.
Babel
Let's recall that we use Babel to build our bundles. In more detail, we use the preset-env.
This is where the fun begins:
We can use the Browserslist integration. Simply look at the package.json
file.
What and How?
What SHOULD we multithread?
First, we need to identify which parts are blocking our code. The original code has three major parts:
loadIfcFileItems
constructProject
buildGeometry
As we discussed earlier, we cannot build the geometry inside a web worker. That leaves loadIfcFileItems
and constructProject
Let's take a look at this picture:
Your eyes can deceive you, don't trust them. Instead, trust the Chrome DevTools Performance panel.
We can see that loadIfcFileItems
and constructProject
takes roughly the same amount of time to compute.
What CAN we multithread?
We must consider one thing.
What can we parse independently of other IFC entities?
If you know your A, B, and (IF)C
, then you realize that we cannot do that much. The IFC schema realizes heavily on references to other entities.
Therefore, the only thing we can do is loadIfcFileItems
independently.
Using multiple Web Workers
How do we load IFC file items independently?
The first thing we need to do is to split up the IFC into different parts. One approach is to split the file itself into several parts. My approach is to split each IfcType
into groups.
In layman's terms:
Let's load all
properties
using one Web WorkerLet's load all
materials
using one Web WorkerLet's load all
building elements
using one Web WorkerLet's load all
relationships
using one Web Workeretc. etc.
See examples/web-worker/worker/utils/custom-ifc-types.js
for more info.
How do we construct multiple Web Workers?
Now that we have figured out how to divide our IFC file, let's look at how we spawn our nested Web Workers
. Take a look at multi-worker.js
, on line 32:
A simple for loop
will do the trick. Each Web Worker
can work on its own. Once its done, it will call the function workerDone
.
The global variable loaded
will store ALL the loaded data. In other words: loaded
will store the result from each web workers.
Since the Web Works parse different IfcTypes, the result will not conflict.
We can do a dirty and quick check to see if multiple Web Workers
are running.
Merging the result
We now have all the loaded data. But, remember that we have used specific Web Workers
to parse the loaded data.
We are missing the references to other entities!
We can simply fix this by running this command AT THE END (!).
Then its a matter of constructing the project like before.
Final notes
This is a very dirty and simple approach. Take a look at these commits for a general understanding of what I did.
Last updated