Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Too bad browser JS is single-threaded. If you switch windows the background application stops. Kind of limits its ability as a desktop replacement no matter how much effort they put into it.


There's no reason you can't have multiple "apps" running at the same time, you just don't have preemption ( https://en.wikipedia.org/wiki/Preemption_(computing) ) so it's possible for one application to tie up the CPU indefinitely. That's definitely not whats happening in this case, since the UI is still responsive.

Alternatively, to get true isolation and preemptive multitasking you could have a sort of "window server" that sends UI events to Web Workers and received drawing commands of some kind (a React virtual DOM?)


You don't need web workers, you just need to host each app in a sandboxed iframe. Then it can render however it wants with normal DOM access and have script and DOM isolation from the OS and other apps. You would need some sort of IPC system on top of postMessage, and probably some way to send theme data down into the frame and get things like content sizes back out.

I don't think same-origin iframed apps would be out-of-process in Chrome yet, but I do think Chrome is supposed to get out-of-process frames eventually. That would prevent an apps from exploiting a browser bug to take down the whole tab.


What is the reason for requiring the single thread of execution in JavaScript? Trading race conditions for callback hell?

Even the concurrency provided by web workers, suffer from the same issues, you communicate with them via messages and they will not respond to messages if they are looping away somewhere else.

I'd love to have some simple pre-emption in JavaScript. Suspend code execution at one point and pick it up at another. Instead of having threads, have the fundamentals that allow threads. Has this been discussed and rejected by the JavaScript community?

I'd really like to know what the deal is here


I don't understand the limitation you are implying with web workers and message passing? If a normal thread is also "looping away somewhere else" it will be equally unresponsive as as web worker not picking up messages. The alternative to message passing would be shared data structures and mutexes, not very nice.


There are many alternatives to "fire-and-forget message passing" that JavaScript does, that don't require shared data structures or mutexes.

JavaScript can implement some of these alternatives with it's postMessage/onmessage combination, but it requires cooperation on both the sender and receiver which (in my opinion) is a limitation: The supervisor/operating system can expose just a little bit more information and it means the system isn't equally unresponsive anymore. Two that I'm thinking about are:

• Mailboxes. A process can post a message to a remote buffer and also check the fullness of that buffer so it can make other arrangements (e.g. scheduling another worker, letting the user know that the system is busy, etc). JavaScript can simulate this if both sides cooperate by implementing an ack-on-receive. UNIX allows detection of a full-buffer (EWOULDBLOCK). KDB publishes[1] the number of bytes in the output buffers which would also be preferable to what JavaScript does.

• Bulletin Boards. A process can simply publish information in a local buffer. Workers can then connect to pick up tasks. Again, JavaScript can simulate this if both sides cooperate, and implement a get/put system with postMessage/onmessage, and while this does represent a shared data structure, it's read-sharing which doesn't require any mutual-exclusion. You can also build it into a network protocol: My cexec[2] does this because load+network latency gives me free scheduling. Many mail servers also use this trick- one process writes to the queue directory, and workers pick up new work whenever they have time.

If you're interested in inter-process communication, Tanenbaum gave good writeup[3] on these methods (which I think are specifically relevant), and some other methods (which are useful in other circumstances).

[1]: http://code.kx.com/wiki/Reference/dotzdotW

[2]: https://github.com/geocar/cexec

[3]: http://www.amazon.co.uk/Modern-Operating-Systems-Andrew-Tane...


Good points, multiple workers on a single shared queue aren't exactly convenient with just a one way postMessage.


A pre-emption mechanism would be able receive the message and respond. At the very least a response of "I'm busy" is better than no response that could be for any number of reasons.

Shared data structures would enable this, and while you may not think they are very nice, I would prefer a not very nice solution to no solution whatsoever. I have seen discussions on various mailing that indicate that shared data structures will be implemented in some manner.

Look at the example number crunching worker given in the spec. https://html.spec.whatwg.org/multipage/workers.html#a-backgr...

    var n = 1;
    search: while (true) {
      n += 1;
      for (var i = 2; i <= Math.sqrt(n); i += 1)
        if (n % i == 0)
         continue search;
      // found a prime!
      postMessage(n);
    }
How would you implement this worker in such a way that the host page could call

  worker.postMessage( {"command": "startfrom", "value" : 131071} ); 
to get the prime calculator change it's search point?


Convert the while/for loops and recursion to continuation-passing style and bounce via nextTick/setTimeout to convince yourself that shared data structures still aren't required to fix this: only pre-emption.


I'm not sure I follow the bit about convincing myself. Going back to square one again with a setTimout/event loop renders much of the use of workers pointless, you are stuck back at the same restrictions as main thread JavaScript.

I agree pre-emption would allow this without shared data structures. It just seems that the solution we will be given in the end will be a shared model.

http://lars-t-hansen.github.io/ecmascript_sharedmem/shmem.ht...


You can get a lot of mileage out of specialised solutions, and I suspect we'll continue to see those instead of a shared model; in an answer to your question about finding prime numbers, simply kill the worker and start another one with a new initial state.


The single thread limitation is caused by the global interpreter lock[0] that's common to most interpreted languages. Along with JS, it also appears in CPython and Ruby MRI, the reference implementation of Python and Ruby respectively.

[0] https://en.wikipedia.org/wiki/Global_interpreter_lock


That's not the reason.

As I understand it, the GIL is an implementation detail of certain interpreters that prevents threads from running on multiple OS threads (and thus multiple CPUs).

JavaScript has explicitly chosen not to support preemptive multithreading at all (aside from Web Workers which don't share memory), while Ruby and Python do have it, even if it can't fully utilize multicore processors.


No, it's not. MRI for example uses OS-level threads from 1.9.x onwards. The GIL prevents multiple of those threads from executing inside the interpreter at any given time, which may sound like it forces a single thread to be running but in practice most typical code will end up spending a lot of time running in C extensions or waiting on kernel space, so it's much less of a hindrance than you might think (it's still not great, but it's far better than it'd be otherwise)


That doesn't eliminate the possibility of pre-emption though does it?

A theoretical version of setTimeout that triggered immediately suspending the active code and executing the timeout function then resuming (or potentially not).

That only requires the interpretor to execute one piece of code at a time. The notions of thread safety would apply to the interpreted code, but not to the interpretor itself.


It certainly looks as if each app lives in its own process of sorts - check the 'process viewer'

I'm sure they could use some sort of thread/process implementation with a scheduler to do stuff. Speculation, each program could be compiled to some sort of bytecode, use asm.js to implement the guts of the thing, etc.

When you think about it, a single-core machine is "single threaded" as well, you just need some interleaving code to let more than 1 thing run at a time, and from some casual usage of the demo, seems they've done exactly that, so there you go


A single core machine can multi thread, but without a timer interrupt it's hard work. What can JavaScript do to provide an interrupt short of emulating a processor with an interrupt via some form of:

  while true() {
    do an instruction;
    check for interrupt;
  }
It's not an efficient way to go.


If you're going to do it that way, then might as well use jslinux[1].

[1]. http://bellard.org/jslinux/


This is just an event loop, no?


In a sense it is, and in a way that is the problem with the current model of JavaScript.

That line

  do an instruction;
Is the smallest unit of code execution. In JavaScript* that is an event. Let's call it a wibblywoop.

JavaScript is effectively designed around the premise that a wibblywoop takes a negligible amount of time. This premise is false. Oftentimes it does take a negligible amount of time, when it doesn't the impact of responsiveness is severe. This is why everything becomes a callback. The language itself has indicators that this should not be the case. the existence of things like Array.Map shows that there was certainly an intention at some point for a function to be able to do a significant workload and return a result.

* in implementations anyway. The language itself doesn't seem intrinsically bound to the event model.


> If you switch windows the background application stops.

> desktop replacement

If it replaces the desktop, there is no other window to switch to.

The problem would be with apps that block, since all multitasking (excluding web workers, but they can't do UI) must be cooperative.


Web workers




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: