Search code examples
javascriptperformanceweb-worker

Spawn WebWorker when needed or reuse the same one?


I'm creating a WebGL game which requires a WebWorker to do some mesh processing, preventing lag on the main thread.

My question - is it better to spawn/create new WebWorkers when needed and terminate them when the job is done, or create one permanent WebWorker which queues the mesh processing internally? Does spawning (and destroying) new WebWorkers create a large overhead?

The main advantage of creating them when needed is having multiple running at once with no backlog of processing waiting to be done, meaning faster mesh generation.

Would appreciate any advice so I can optimize my code for the best performance. Thanks!


Solution

  • This isn't really a WebGL question it's just a general WebWorker question. Off the top of my head though it depends. Workers are just threads. If your threads are busy 100% of the time (not waiting for IO or user input or the next frame) then you won't get any speed up once you have more threads than cores.

    In other words if you have 2 cores, and 3 threads each running without waiting for anything than 1 core will be running 1 thread 100% of the time and another core will be running each of the other threads 50% of the time. The total time will be the same as if you had combined 2 of the threads into 1.

    So, spawning a ton of threads isn't necessarily a win and there is a way to query the number of cores the user's machine has in JavaScript in the browser.

    On top of that, you're processing meshes which might be large data. Let's say each mesh uses 200meg while being processed (like it's in JSON) and 100meg when finished (you've read the JSON and converted to Float32Arrays etc..) In other words, when you're done you'll have 1gig of data (ten 100meg meshes)

    So, you spawn 10 workers. When they are finished there will only be 1 gig of data left (the final 10 meshes) but as they are running each uses 300meg (200meg to read in the JSON, 100meg to store the result). That's 3 gig of memory total while they're running. You might run out of memory.

    Where as if you had just one mesh processing worker with a queue of work to do the most memory you'd use is 1.2 gig. The worker would read the JSON (200meg) convert to Float32Arrays (100meg), pass those Float32Arrays to the main page, then work on the next mesh.

    There's 3 paths I see

    1. Spawn a worker to process mesh. When it's done terminate it. Spawn a new one.

      Spawning a workers is not free as it has to load the javascript each time?

    2. Spawn a worker per mesh.

      See above why that might not be a good idea

    3. Spawn a worker and give it a queue of meshes to work on.