Closed jvilk closed 8 years ago
Current roadblock:
The worker lives in its own scope, separate from anything included in index.html
, so we'll need to manually include what we need with importScripts
. This is a little annoying, especially because it means we need to know whether to include things separately (in dev mode) or as one chunk (in release mode).
More importantly, we can't import the browser/node.js
code directly, because it depends on having access to window
. However, messages between the main thread and the worker are all asynch, so it'll be a pain to rewrite all the node.fs.readFileSync
calls. The calls to node in src/natives.coffee
will also need attention, I suspect.
I was hoping that WebWorkers would have a way of polling for new messages, but a quick Google didn't find anything. Hmm.
As for the window
issue, I think you can just define things on self
, which is the WebWorker global scope. I actually think that self
aliases to window
in the main JavaScript thread, too... :)
For the file system, the easy way out is to completely replace the synchronous API with an asynchronous API that abuses setTimeout
. You will have to somehow propagate a callback up to the localStorage
code so that it can be put into the message sending callback, though (or maybe do a nasty hack involving a variable in a higher scope rather than changing all of those functions; then I can later refactor the hack).
The localStorage
code can have an if
/else
statement that uses the existing code if we are not in a WebWorker
.
These changes should preserve compatibility with Node and IE.
I disabled the localStorage
-based filesystem stuff in node.coffee
(see commit 8201078eb57111eb5d53e0e9c5f0d3d9f0877d73) and after some effort, everything works! I'm frankly amazed.
Known issues:
LocalStorageSource
, so file upload and editing is essentially a no-op.Being able to scroll the page while Doppio runs is super fun. :hotsprings:
Being able to scroll the page while Doppio runs is super fun.
Or, in the case of Firefox, being able to use the web browser while Doppio runs.
I've been working on this for ( sigh ) a few days now. CJ's initial effort worked, but had one critical issue: The filesystem lived in the JVM. This meant that it could not use localStorage
, and was not in "sync" with what the terminal saw.
If we kept the filesystem in the frontend, we would have to switch over to asynchronous file operations in the JVM. If we put the filesystem in the JVM, we would have to switch over to asynchronous file operations in the frontend and in the JVM, since the JVM would need to use messages to get at localStorage
content.
Naturally, we decided to keep the filesystem in the frontend. For now, frontend will still use the synchronous file API, since our virtual filesystem is still blocking. At some point, we'll rewrite/refactor it to be asynchronous, which should hopefully make it more amenable to eventual Dropbox/GDrive/etc. integration. :) I'll create an issue for that.
There are two daunting subtasks on the road to WebWorker-ization that can be done in master before we hook up magical message passing. I will create an issue for each of these.
fstatSync
, read
, write
...). This also prevents the overhead of having to de-construct and re-construct the Doppio file object.class_lookup
asynchronous: This is unavoidable, since read_classfile
needs to read a file asynchronously. This is going to be a painful change, as we currently call class_lookup
fairly frequently. During post-change optimization, we will likely want to introduce more caches.Once those are done, my local WebWorker changes (which I dare not commit to the WebWorker branch yet, as the JVM is totally borked) should be able to integrate with master nicely.
Now that we're using BFS, the synchronicity issues we were having before should be no problem. This issue will probably need to wait until we're done with the Typescript conversion, though, for our sanity's sake.
Totally agree. Note that this will also complicate any Swing work, but we can deal with that later.
EDIT: Note that we will need to add a WebWorker proxy interface to BFS for this.
The doppio library is separate from the frontend now, so we could potentially do this now. Here's what would be required:
What is the status of "in web worker" runtime? can we now run doppio solely from a web worker? We do not need the front end part. Probably a separate question but, is it possible to preload java.lang, java.util, and java.io packages?
I'm not sure right now, but I'll be looking at this in the next few weeks
I have no reason to believe that this would not work. This issue refers to exposing a concise API for invoking DoppioJVM in a WebWorker (e.g. new Doppio({webworker: true})
). Right now, DoppioJVM should work in a WebWorker, but there's no plug-and-play API to make it simple.
I think there is no need for an extra API. Just a simple postMessage/onmessage communication protocol would be enough to invoke DoppioVM. A front end API should not be a focal point of DoppioVM. Let the developers find their own way on that front.
DoppioJVM works just fine in a webworker; I didn't even need to change anything. I just made a commit that switched to using WWs for testing, so I'm closing this out.
The only issue currently is a (throughput-based) performance regression in a WebWorker compared with the main thread, which I'm actively investigating.
We can run DoppioVM only in a web worker because the main thread is already busy with tons of other stuff. Could you open another issue for the performance regression so that we can follow the imrpovements on that? just a thought :).
Sure, I'll do that. I'd also appreciate stars on this Chrome issue, which seems to be the culprit in Chrome:
I haven't checked to see if performance differs in other browsers yet.
Doppio currently runs in the main JavaScript thread, which causes the browser to be less responsive than desired. While we could "fix" this by yielding the thread more often, this comes with a speed penalty.
For browsers that support it, we should run the JVM in a WebWorker. Note that we are not mapping threads to WebWorkers -- simulating shared memory would be too slow / cumbersome / difficult -- we are mapping JVM instantiations to WebWorkers.
The main JavaScript thread would be responsible for checking for and handling messages sent from the WebWorker for various events, such as:
localStorage
.localStorage
.For browsers that do not support WebWorkers (e.g. IE before 10), we can just simulate WebWorkers in the main JavaScript thread. To improve those web browsers' responsiveness, we could just yield the JavaScript thread after a certain duration of time (easy enough to do in the interpreter).
This should not impact the Node JS frontend. It will just impact how the browser frontend runs the JVM, how the node emulation requests
localStorage
files, how printing to/receiving input from the console works, and any other browser-specific features that we add to Doppio in the future.