Do all javascript webworkers for a page operate on a single separate thread from the main page, or does each webworker get its own thread?
For context:
I have a large amount of data that is currently being processed by one webworker. Would it be faster to split it up across 10 webworkers, or will they all use the same thread?
That is not defined by the standard:
This standard does not define the precise mechanism by which this is achieved, be it time-sharing cooperative multitasking, fibers, threads, processes, using different hyperthreads, cores, CPUs, machines, etc.
Even if each webworker gets its own thread, the CPU is not able to run them in parallel, if the number of cores is lower then the number of web workers. Also other threads are using the CPU.
Web workers have not exactly been made for you scenario. They are more of a 'don't block the UI' thing. See also this statement from the standard:
Workers (as these background scripts are called herein) are relatively heavy-weight, and are not intended to be used in large numbers
The only sensible thing to do is to test what works best (with all relevant browsers). You can check self.navigator.hardwareConcurrency (see here) in your code to decide how many workers you should spawn.
Related
I keep reading about JavaScript implementations being single threaded, so I was wondering if it means that it takes a single logical thread of a CPU? or are software threads completely different from hardware threads?
(V8 developer here.)
JavaScript implementations being single threaded
That's not quite correct. JavaScript as a language is single-threaded. That means it doesn't give you, the programmer, a way to say "please start a new thread running this code here in parallel to my other code". Only one of your functions will execute at a time. A new function (e.g., a scheduled callback) can only start executing when the currently executing function has returned.
(Web workers are not a contradiction to this. They do execute concurrently with your main code, but that's not a JavaScript language feature. Instead, the browser environment gives you a way to spawn an independent second instance of a single-threaded JavaScript execution environment.)
JavaScript implementations, i.e. engines, are free to use as many threads as they want for background tasks. For example, when you use asynchronous DOM features (like the fetch API), then typically another thread takes care of doing the work (in this case, the fetching) in the background (typically on another CPU core). Once the result is available, a callback is scheduled, which has to wait until the single main thread is free to execute it. For V8 specifically, I can tell you that it also uses background threads for parsing and compiling JavaScript code, as well as for garbage collection. (Other engines probably do that too, but I don't know them as well.)
are software threads completely different from hardware threads?
Well, a software thread is a "thread"/strand/sequence of execution that wants to run, and a "hardware thread" is the hardware's ability to execute it. Personally, I think "hardware thread" is a confusing misnomer, and it would make more sense to call it "(logical) CPU core" instead; at any rate it amounts to the same thing.
So yes, a single-threaded program will run on one hardware thread (or not run at all). JavaScript programs themselves are single-threaded (this is defined by the language), but engines running the program typically use several threads (i.e., several software threads running on several "hardware threads"/CPU cores).
A software thread, at any given time, is executing at most in only a single CPU core. I have included the "at most" because a software thread can be in a bunch of states other than execution in which it isn't running (it can be waiting, sleeping, dead...).
You have no guarantees that a software thread executes always on the same CPU core. Although, for performance reasons (mostly related to caches), your operating system thread scheduler will probably try to execute a thread always on the same core.
Hardware threads (or logical cores, because the operating system sees them as if they were real hardware cores) are a feature of some processors that allow multiplexing the execution of several threads on the same core under some condition. For example, you can execute two threads in a single core if you have twice the registers and both are using different parts of the core or waiting (e.g. one is adding numbers while the other is doing logical operations) at any instant of time.
In summary, your operating system is, probably, using the same core for your JavaScript engine most of the time it is executing, but you really shouldn't rely on this assumption for anything.
Is web worker just a normal native thread created by browser to run and communicate with other browser threads with a messaging queue? Or doesn't it contain other things when created?
I'm looking at the experimental support of pthread in emscripten, multiple threads in C++ will be translated to web workers once compiled. But will it have the same level of performance as native code? After all fine grained multithreading is a key feature in C++.
At the moment, WebWorkers are pretty heavyweight because the VM duplicates a bunch of its internal state (sometimes even re-JITs code for a worker). That state is much bigger than a native thread's few MiBs of initial stack space and associated state.
Some of this can be fixed by implementations, and I expect that if SharedArrayBuffer or WebAssembly + threads become popular then browser engines will want to optimize things.
That being said, the end of your question hints at a misunderstanding of what thread overheads are, and how the proposal for SharedArrayBuffer (which Emscripten relies on to support pthreads) works. WebWorkers are heavy at the moment, but they can communicate through SABs in exactly the same way native code such as C++ can: by accessing exactly the same memory, at the same virtual address. SAB adds a new kind of ArrayBuffer to JavaScript which doesn't get neutered when you postMessage it to another worker. Multiple workers can then see other worker's updates to the buffer in exactly the same way C++ code when you use std::atomic.
At the same time, workers can't block the main thread by definition and therefore have a more "native" feel. Some web APIs aren't available to all workers, but that's been changing. This becomes relevant if you e.g. write a game and have network / audio / render / AI / input in different threads. The web is slowly finding its own way of doing these things.
The details are a bit trickier
SAB currently only supports non-atomic accesses, and sequentially-consistent accesses (i.e. the only available Atomic access at the moment is the same as C++'s std::memory_order_seq_cst). Doing non-atomic accesses should be about as performant as C++'s non-atomics (big compiler caveats here which I won't get into), and using Atomic should be about as performant as C++'s std::atomic default (which is std::memory_order_seq_cst). C++ has 5 other memory orders (relaxed, consume, acquire, release, acq_rel) which SAB doesn't support at the moment. These other memory orders allow native code to be faster in some circumstances, but are harder to use correctly and portably. They might be added to future updates to SAB, e.g. through this issue.
SAB also supports Futex which native programs rely on under the hood to implement efficient mutex.
There are even trickier details when comparing to C++, I've detailed some of them but there are even more.
Recently in school, I've been taught C++/OpenMPI in a parallel computing class. I don't really like to program in C++ as its low level and harder to program, easier to make mistakes etc.
So I've been thinking, is JavaScript/NodeJS (something I've started to like) actually truly parallel? Or is it simply using non-blocking operations to simulate parallel execution (which I think it is)? There are libraries like async which gives similar functions to what I've used in OpenMPI: gather, scatter even "parallel". But I've got a feeling its just simulating parallelism using non-blocking IO?
Perhaps only node-webcl is truly parallel?
UPDATE: Seems possible via web workers (~31 min): watching http://www.infoq.com/presentations/Parallel-Programming-with-Nodejs
In deed, JavaScript is single-threaded by it's design. But you're not the first person who wants some parallelism in it, so there're some things that can work truly parallel:
WebWorkers - run in threads, which means that they quite cheap to create. They limited in data interchange abilities. At first, you could only send messages between workers, but now they are a lot better, you can even use SharedArrayBuffer for concurrent memory access. Not supported in NodeJs, only in browsers.
WebGL/WebCL - utilize graphic subsystems for parallel computing. Very fast, but effective for a limited set of problems. Not all tasks can be computed effectively on GPU-like subsystem. It also requires additional data transformations for presenting you data in pixel-like format. Has decent browsers support as WebGL, but as you've already mentioned has only experimental implementations for NodeJs.
SIMD - parallelism over data. It was a promising thing, but it is no longer on the roadmap for JavaScript and it will be a part of the WebAssembly standard.
Cluster - a NodeJs solution for parallelism. Allows to run multiple processes (not threads) and even supports SharedArrayBuffer for communication since 9th version.
That's pretty much it. There's also the WebAssembly threads proposal, but, firstly, it is a proposal and, secondly, WebAssembly is not JavaScript.
In general, JavaScript is by far not the best tool for low level parallel computing. There're a lot of other tools that suit better for this: Java, C#, Go...
With Node.js, your JavaScript runs in a single thread. IO is non blocking.
The new JavaScript engine takes advantage of multiple CPU cores through Windows to interpret, compile, and run code in parallel. - http://technet.microsoft.com/en-us/library/gg699435.aspx
and
The Chakra engine interprets, compiles, and executes code in parallel and takes advantage of multiple CPU cores, when available. - http://msdn.microsoft.com/en-us/ie/ff468705.aspx
Wait, what?!? Does this mean we've got multi-threaded parallel JavaScript code execution (outside of web-workers) in IE9?
I'm thinking this is just a bad marketing gimmick but would like to see some more info on this. Maybe they mean different browser windows/tabs/processes can utilize multiple CPUs?
Conclusions, based largely on the comments and hence provided as a community wiki answer so that this question ends up with an actual answer:
It's likely that Microsoft mean that the separate tasks of (i) interpreting and/or running; and (ii) compiling occur in parallel. It's probable that they've applied technology like Sun's old HotSpot JVM so that the Javascript virtual machine interprets code at the first instance because it can start doing that instantly. It also JIT compiles any code that appears to be used sufficiently frequently for doing so to be a benefit. It may even have different levels of compiler optimisation that it slowly dials up. In that case it may be using multiple cores to interpret or run one fragment of code while also compiling arbitrarily many others, or even while recompiling and better optimising the same piece of code that is being run.
However, it's also possible on a technical level that you could perform static analysis to determine when callbacks are mutually independent in terms of state, and allow those callbacks to execute in parallel if the triggering events prompted them to do so. In that way a Javascript virtual machine could actually interpret/run code in parallel without affecting the semantically serial nature of the language. Such a system would be logically similar to the operation of superscalar CPUs, albeit at a much greater remove and with significantly greater complexity.
I'm new to JavaScript so forgive me for being a n00b.
When there's intensive calculation required, it more than likely involves loops that are recursive or otherwise. Sometimes this may mean having am recursive loop that runs four functions and maybe each of those functions walks the entire DOM tree, read positions and do some math for collision detection or whatever.
While the first function is walking the DOM tree, the next one will have to wait its for the first one to finish, and so forth. Instead of doing this, why not launch those loops-within-loops separately, outside the programs, and act on their calculations in another loop that runs slower because it isn't doing those calculations itself?
Retarded or clever?
Thanks in advance!
Long-term computations are exactly what Web Workers are for. What you describe is the common pattern of producer and/or consumer threads. While you could do this using Web Workers, the synchronization overhead would likely trump any gains even on highly parallel systems.
JavaScript is not the ideal language for computationally demanding applications. Also, processing power of web browser machines can vary wildly (think a low-end smartphone vs. a 16core workstation). Therefore, consider calculating complex stuff on the server and sending the result to the client to display.
For your everyday web application, you should take a single-threaded approach and analyze performance once it becomes a problem. Heck, why not ask for help about your performance problem here?
JavaScript was never meant to do perform such computationally intensive tasks, and even though this is changing, the fact remains that JavaScript is inherently single-threaded. The recent web workers technology provides a limited form of multi-threading but these worker threads can't access the DOM directly; they can only send/receive messages to the main thread which can then access it on their behalf.
Currently, the only way to have real parallel processing in JS is to use Web Workers, but it is only supported by very recent browsers. And if your program requires such a thing, it could mean that you are not using the right tools (for example, walking the DOM tree is generally done by using DOM selectors like querySelectorAll).