runtimejs / runtime

[not maintained] Lightweight JavaScript library operating system for the cloud
http://runtimejs.org
Apache License 2.0
1.93k stars 128 forks source link

Multicore #7

Closed danielearwicker closed 10 years ago

danielearwicker commented 10 years ago

Will userland JavaScript all run in a single thread and therefore only be able to run on a single core of (say) an eight core system?

piranna commented 10 years ago

Teorically it's possible, Node.js has support to run several process on the same events queue thanks to work on Atom, and it's on the roadmap to allow to consume that events queue from several threads for v1.0. Also, according to runtime.js docs, the intentios is to run one V8 isolate per core, so the answer is yes, thanks to the work in several layers, in the long term there will be support for multicore processing inside runtime.js :-)

groundwater commented 10 years ago

@danielearwicker v8 allows parallel execution of multiple isolates. Each isolate contains its own v8 heap, and one isolate can house many contexts.

There are two strategies here:

  1. load one isolate per core, and separate processes by context
  2. load one isolate per process

The former approach is easier, and faster, but processes are bound to the isolate they were spawned in. This means two processes that share an isolate cannot run in parallel.

The latter approach is a little heavier, but means processes can all run in parallel.

iefserge commented 10 years ago

Multicore support is planned. It's partially implemented and very unstable. Disabled by default. It will be possible to use other available cores similar to a fixed size thread pool (or web worker pool) when it's done.

Currently it's one isolate per core and separate context for every program. This way, for example, programs on the same isolate can share transferred JSON strings on the same heap. So in this case IPC would be much faster, because no additional copy required.

groundwater commented 10 years ago

I believe objects allocated outside the v8 heap can be shared between isolates (barring concurrency issues). Steps to share data between isolates:

  1. allocate a buffer (raw memory) outside any v8 heap
  2. store the pointer in a v8 object in each isolate
  3. provide bindings to read/write to the buffer

Unless you need the contents of the buffer as a JavaScript string object, you do not need to copy the data into the respective heaps.

iefserge commented 10 years ago

Yes, but only if you can control buffer allocation step. It works for ArrayBuffers, but not strings. V8 uses isolate heap to allocate strings created by JS code.

groundwater commented 10 years ago

A few issues with contexts for people to be aware of:

  1. A while(true) true loop will hang an isolate, and no other contexts in the same isolate can run while it's executing. As @iefserge said, multi-context means cooperative multitasking. Contexts in the same isolate cannot preempt each other.
  2. A context that is hung cannot be stopped without collapsing the entire isolate. This will bring down every other context sharing the isolate.
  3. Contexts cannot jump isolates. If one isolate happens to contain all the CPU-heavy processes, they cannot be rebalanced across CPUs.
  4. Contexts share a heap, so it's possible to pass whole JavaScript objects between contexts. It is possible for one context to mess with another without due caution. For example, if an array is passed between contexts, the receiving context may walk to Array prototype chain of the first and mess with it.

I'm interested in exploring the one-isolate per process model, and I'll help where I can. My v8 programming is alright, and I know how the MMU works etc, but there are some wide gaps between my skills and what you're doing here. I'm very interested in this, so I'm game for learning more.

iefserge commented 10 years ago

V8 supports context interruption. Engine puts interrupt guard checks into every function and every loop. So its possible to interrupt context even in a middle of infinite loop. Preemptive multitasking is a planned feature. Yes, system doesn't solve multicore balancing problem for applications automatically. The idea is that every app can use available cores on a machine similar to a fixed size thread pool. So it can manually schedule tasks for available cores. The think the biggest problem with isolate-process solution is that v8 isolates are heavy. But we can experiment with this, of course.

groundwater commented 10 years ago

V8 supports context interruption. Engine puts interrupt guard checks into every function and every loop. So its possible to interrupt context even in a middle of infinite loop.

I believe you can interrupt the isolate, but you cannot resume another context in it's place. Basically a misbehaved context ruins the party.

The idea is that every app can use available cores on a machine similar to a fixed size thread pool. So it can manually schedule tasks for available cores

This works for short tasks, but if long running tasks happen to collect on a single isolate, there's no way to rebalance them.

The think the biggest problem with isolate-process solution is that v8 isolates are heavy. But we can experiment with this, of course.

I agree, and think there is probably a reason to use both freely. For example, a shell may want to run it's commands in new contexts, which would let shell commands process whole objects, e.g.

$ find . | print this.ctime

Where the find command emits an object consumed by the print command. This is similar but not a one-to-one mapping to the differences between threads an processes.

I would love to experiment with both.

RangerMauve commented 10 years ago

@groundwater Kinda off topic, but if there's a shell, it'll be in JavaScript, right?

groundwater commented 10 years ago

but if there's a shell, it'll be in JavaScript, right?

@RangerMauve yes :smile:

heapwolf commented 10 years ago

adding to roadmap / wiki