JavaScript multithreading
Asked Answered
R

5

34

I'm working on comparison for several different methods of implementing (real or fake) multithreading in JavaScript. As far as I know only webworkers and Google Gears WorkerPool can give you real threads (ie. spread across multiple processors with real parallel execution). I've found the following methods:

  • switch between tasks using yield()

  • use setInterval() (or other non-blocking function) with threads waiting one for another

  • use Google Gears WorkerPool threads (with a plugin)

  • use html5 web workers

I read related questions and found several variations of the above methods, but most of those questions are old, so there might be a few new ideas.

I'm wondering - how else can you achieve multithreading in JavaScript? Any other important methods?

UPDATE: As pointed out in comments what I really meant was concurrency.

UPDATE 2: I found information that Silverlight + JScript supports multithreading, but I'm unable to verify this.

UPDATE 3: Google deprecated Gears: http://code.google.com/apis/gears/api_workerpool.html

Reremouse answered 3/10, 2011 at 18:42 Comment(3)
I think you're question is how else can you achieve concurrency in Javascript. As you said calling yield() or using setInterval() doesn't count. Also web workers aren't exactly like native OS threads as the code must be isolated in a separate file and only communicate back using events. As well, workers may or may not be using real OS threads under the hood -- although they allow you to achieve a similar kind of concurrency without thinking.Nonrigid
Exactly. My bad for not using proper vocabulary.Superfamily
Plugins aside, I think your list is pretty good. I think web-workers are really the best (most-compatible) way to go, although they aren't guaranteed to use multiple CPU cores, it would depend on the JavaScript engine.Nonrigid
W
29

Web Workers. They’re a W3C standard (well, a working draft at the moment) for exactly this, and require no plugins:

This specification defines an API that allows Web application authors to spawn background workers running scripts in parallel to their main page.

The specification also discusses spreading workers across multiple cores, for true concurrency (this is handled invisibly by the browser’s JavaScript engine):

With multicore CPUs becoming prevalent, one way to obtain better performance is to split computationally expensive tasks amongst multiple workers. In [one] example, a computationally expensive task that is to be performed for every number from 1 to 10,000,000 is farmed out to ten subworkers.

yield() and setInterval() only schedule things to happen later, they don’t run concurrently with anything else.

Whaling answered 7/10, 2011 at 4:31 Comment(6)
But +1 for the link, someone looking for concurrency in JS might find it usefulSuperfamily
@KrzysztofHasiński I think that Web Workers are the best/only way to have multiple threads in JavaScript in the browser, right now.Whaling
I agree, it is the best way, but I don't really want to choose the best one, I just want to gather different methods and compare implementations (in Chrome and Fx) and performance for a short lecture.Superfamily
After a really long time there isn't anything new and I'd like to point people looking for a way to do concurrency in JS to a right direction to do it so I accept this answer :)Superfamily
To really use power of Web Workers you have to use "transferable objects" which allow moving of big chunks of data between main thread and workers without copying. Passing objects "structured copying" can often defeat the performance benefit of using workers.Beitnes
It seems like multipe webworkers don't improve speed on big tasks... #44808854Maddeu
P
4

I'm wondering - how else can you achieve multithreading in JavaScript? Any other important methods?

You can have your code transformed into JavaScript code that doesn't have any explicit loops or direct function calls, instead code is divided into small units of execution that are managed by a threading engine. In my example code I show how a function with loops would be transformed but I've omitted the mechanism for function calls just to keep the example simple.

The process of transformation basically works by splitting code at division points. These division points are function calls and loops (as demonstrated above). In the example I've used objects and keys but it may be much easier on the browser's JavaScript engines if the units stored the stack as an object variable (i.e. storing using this.foo = bar instead of stack["foo"] = bar).

For example the following code:

// Phoney method purely to demonstrate structure
function Foo() {
  var i,
      sum = 0,
      accumulator_list = [],
      accumulator_modulus = [],
      kMaxAccumulatorCount = 100;

  // Calculate accumulations
  for(i = 0; i < kMaxAccumulatorCount; ++i) {
    current_accumulator = GetNextAccumulator()
    accumulator_list[i] = current_accumulator;
    sum = sum + current_accumulator;
  }

  // Calculate accumulator modulus
  for(i = 0; i < kMaxAccumulatorCount; ++i) {
    current_accumulator = accumulator_list[i];
    accumulator_modulus[i] = current_accumulator % kMaxAccumulatorCount;
  }
}

... into something like this:

function Foo_A(caller,stack) {
  var stack = {};
  stack["i"] = undefined;
  stack["sum"] = 0;
  stack["accumulator_list"] = [];
  stack["accumulator_modulus"] = [];
  stack["kMaxAccumulatorCount"] = 100;

  stack["i"] = 0;
  return {caller: caller, stack: stack, next=Foo_B};
}

function Foo_B(caller, stack) {
  stack["current_accumulator"] = GetNextAccumulator();
  stack["accumulator_list"][stack["i"]] = stack["current_accumulator"];
  stack["sum"] = stack["sum"] + stack["current_accumulator"];

  // For-loop condition satisfied ?
  if(stack["i"] < stack["kMaxAccumulatorCount"]) {
    ++stack["i"];
    return {caller: caller, stack: stack, next:Foo_B};
  } else {
    // Initialise the next for loop.
    stack["i"] = 0;
    return {caller: caller, stack: stack, next:Foo_C};
  }
}

function Foo_C(caller, stack) {
  stack["current_accumulator"] = stack["current_accumulator"][stack["i"]];
  stack["accumulator_modulus"][stack["i"]] = stack["current_accumulator"] % stack["kMaxAccumulatorCount"];

  // For-loop condition satisfied ?
  if(stack["i"] < stack["kMaxAccumulatorCount"]) {
    ++stack["i"];
    return {caller: caller, stack: stack, next:Foo_C};
  } else {
    // Function has finished so the next will be null. When the thread-engine sees this it simulates the behaviour of a return, pops its virtual stack and returns execution to the caller
    return {caller: caller, stack: stack, next:null};
  }
}
Polycotyledon answered 27/5, 2013 at 8:34 Comment(0)
D
3

Multithread.js is a library for really easy multithreading in JS that wraps Web Workers and does the majority of your work for you. :)

Darnall answered 28/2, 2014 at 14:47 Comment(1)
Nice addition, although these are still Web Workers :)Superfamily
L
1

There is no direct support for multithreading in JavaScript. However you can achieve this by applying some ideas and method.

There are methods like:

var id = window.timeout("javascript code", time);

here the JavaScript code is called after the specifed time and we can use

window.clearTimeout(id);

for clearing. By this we can achieve fake concurrency.

Ludvig answered 6/10, 2011 at 5:54 Comment(2)
This is just a variation on setInterval(). And there is a direct way to do multithreading, as pointed out in question (web workers).Superfamily
+1 for mentioning clearTimeout(), I used it for my demo code.Superfamily
F
1

q: how else can you achieve concurrency in Javascript

You can use async or 'non-blocking' type methods. This has one of the major buzzes about the node.js system. It's not exactly multithreaded, but it does tend to be faster.

Fog answered 7/10, 2011 at 0:16 Comment(1)
What other kind of non-blocking methods can be used besides setInterval or setTimeout? Anything working significantly different than those two?Superfamily

© 2022 - 2024 — McMap. All rights reserved.