-
Notifications
You must be signed in to change notification settings - Fork 322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run ydoc-server with GraalVM #9528
Conversation
} | ||
|
||
public static void main(String[] args) throws Exception { | ||
ClasspathResource.createTempFile(WASM_PATH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to @kazcw we should just call the Parser.parseInput instead of trying to load Rust part of the parser as WASM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can, and it would be more efficient--but doing so would have implications for versioning, a topic which I think in the 13-March meeting we decided to decide later. One possibility discussed was the UI injecting the parser (which would be the WASM core and the JS layer) so that the frontend could remain tightly coupled with it, and then we would use something else as the stable interface (I pictured an IrBuilder
API).
If we are definitely OK with requiring the frontend and backend to be versions with the same parser build, we should make the change to using the linked library (and we should add a parser version check to the protocol).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now versioning isn't an issue (everything is packaged as a single deliverable, distribution). But should IDE inject its version of the yserver into (completely) different version of an engine, then relying on engine's parser isn't an option. I should collect these constraints somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now versioning isn't an issue (everything is packaged as a single deliverable, distribution).
Versioning isn't an issue in production, but the only reason versioning doesn't currently seem like an issue during development is that the frontend and backend are loosely-coupled in practice, with our current source-code/span-tree interface. When we move the parser into the ydoc-server, it will become essential that the frontend and backend are using the same parser version (including both the WASM and app/gui2/shared
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Versioning isn't an issue in production
..in current production we provide two kinds of deliverables:
- standalone packages containing both GUI and the backend
- the cloud which also packages GUI and backend of the same release tag like 2024.1.1-nightly.2024.3.26 (right @PabloBuchu?)
With such a setup we may pay no attention to versioning...
frontend and backend are loosely-coupled in practice
... as frontend and backend are build time coupled - e.g. they are build, tested and known to work together. In such a setup it is clear that ...
the frontend and backend are using the same parser version
They do use the same version, as they are built, tested, packaged together.
As such I am suggesting to @4e6 to call the JNI version of the parser. I believe it is a simpler, few lines code change. Running our parser in its WASM version is also possible (there is GraalWasm, but it is more complex to setup and it'd be (slightly) slower, slower to get up to the full speed and more memory hungry because of WASM interpreter metadata overhead. That's why I'd start with integrating the parser via its JNI version. Only then investigate how to integrate the WASM variant.
Please find a link to additional information about incremental compilation plan here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Versioning isn't an issue in production
..in current production we provide two kinds of deliverables:
* [ standalone packages containing both GUI and the backend](https://github.com/enso-org/enso/releases/tag/2024.1.1-nightly.2024.3.26) * the cloud which also packages GUI and backend of the _same release tag_ like [2024.1.1-nightly.2024.3.26](https://github.com/enso-org/enso/releases/tag/2024.1.1-nightly.2024.3.26) (right @PabloBuchu?)
With such a setup we may pay no attention to versioning...
frontend and backend are loosely-coupled in practice
... as frontend and backend are build time coupled - e.g. they are build, tested and known to work together. In such a setup it is clear that ...
the frontend and backend are using the same parser version
They do use the same version, as they are built, tested, packaged together.
Right... "versioning isn't an issue in production."
However, this change would cause some inconvenience during development. Developers frequently use versions other than the packaged versions enumerated above. It is currently possible for frontend developers to pull changes from develop
without rebuilding the backend. I do so frequently, and I expect I am not alone in this. If we make this change, the coupling will be much tighter in practice. Frontend developers (and library developers?) will need to be aware when a commit touches the parser and they need to rebuild the backend. Developers working on the parser will have a much longer code/test cycle. Maybe this is acceptable, but these are costs we should be aware of if we're making this change.
lib/java/js-websocket/src/main/java/org/enso/polyfill/timers/TimersPolyfill.java
Outdated
Show resolved
Hide resolved
lib/java/js-websocket/src/main/resources/org/enso/polyfill/websocket/websocket-polyfill.js
Outdated
Show resolved
Hide resolved
d31f221
to
80bcd19
Compare
lib/java/polyglot-ydoc-server/src/test/java/org/enso/polyfill/EncodingPolyfillTest.java
Outdated
Show resolved
Hide resolved
lib/java/polyglot-ydoc-server/src/test/java/org/enso/polyfill/EncodingPolyfillTest.java
Outdated
Show resolved
Hide resolved
var data = arguments[2].as(int[].class); | ||
|
||
var charset = encoding == null ? StandardCharsets.UTF_8 : Charset.forName(encoding); | ||
// Convert unsigned Uint8Array to byte[] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to obtain .as(ByteBuffer.class)
- I've heard it should be possible to exchange it from/to Uint8Array
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ByteBuffer
interop currently works only with arrays that are backed by the Java buffers https://github.com/oracle/graaljs/blob/master/graal-js/src/com.oracle.truffle.js.test/src/com/oracle/truffle/js/test/interop/InteropByteBufferTest.java
We may try using Value.readBuffer
method to extract byte array without the conversion
lib/java/polyglot-ydoc-server/src/test/java/org/enso/polyfill/EncodingPolyfillTest.java
Outdated
Show resolved
Hide resolved
lib/java/polyglot-ydoc-server/src/main/java/org/enso/polyfill/ClasspathResource.java
Outdated
Show resolved
Hide resolved
lib/java/polyglot-ydoc-server/src/test/java/org/enso/polyfill/EncodingPolyfillTest.java
Outdated
Show resolved
Hide resolved
d71e200
to
f1da6ec
Compare
lib/java/polyglot-ydoc-server/src/main/java/org/enso/polyfill/Main.java
Outdated
Show resolved
Hide resolved
da0280b
to
9d7c750
Compare
lib/java/ydoc-server/src/test/java/org/enso/ydoc/polyfill/ParserPolyfillTest.java
Show resolved
Hide resolved
lib/rust/parser/generate-java/java/org/enso/syntax2/Parser.java
Outdated
Show resolved
Hide resolved
/// Determine the token variant of the provided input. | ||
#[allow(unsafe_code)] | ||
#[no_mangle] | ||
pub extern "system" fn Java_org_enso_syntax2_Parser_isIdentOrOperator( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is also needed here: #8779 (comment)
- from code clarity perspective - we should have just a single implementation
- from performance perspective - it is better to stay in the JVM than jump out and back just to compare letters in a string - the overhead of
input
buffer conversion isn't negliable- not only a JVM vs. JNI problem
- also JavaScript vs. WASM problem
However if the performance wasn't a problem so far, we probably don't need to care. It is more important to get the functionality right.
It's alive! First run with the polyglot ydoc server. ydoc_server_first.mp4 |
I can reproduce your success myself if I: enso$ POLYGLOT_YDOC_SERVER=true npm --workspace=enso-gui2 run build-ydoc-server-polyglot
enso$ sbt ydoc-server/assembly
enso$ POLYGLOT_YDOC_SERVER=true npm --workspace=enso-gui2 run dev Small step for ydoc, but a huge leap for Enso! Congrats. |
I even got debugging working with: enso$ POLYGLOT_YDOC_SERVER_DEBUG=true npm --workspace=enso-gui2 run dev
ydoc: Debugger listening on ws://127.0.0.1:34567/HwpxX-S2_c-dB0qRAMhY-LmSWALU7RSvXF5IBRkgeoA
For help, see: https://www.graalvm.org/tools/chrome-debugger
ydoc: E.g. in Chrome open: devtools://devtools/bundled/js_app.html?ws=127.0.0.1:34567/HwpxX-S2_c-dB0qRAMhY-LmSWALU7RSvXF5IBRkgeoA I can connect to your process via ChromeDevTools: |
a87e4f7
to
f38c358
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approving dashboard changes
(the only changes there is a new ydocUrl
parameter that gets threaded through the entire app to Editor.tsx
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I see the whole support is optional right now - it doesn't affect workflow yet. Let's integrate and move on!
- Please make sure the instructions in PR description to build and use this in the description are correct
- Having a CI test that performs these instructions and runs (and shutdowns automatically) the
ydoc-server
would be a plus, but it is not strictly necessary right now.
@@ -14,6 +14,8 @@ public class Main { | |||
private Main() {} | |||
|
|||
public static void main(String[] args) throws Exception { | |||
System.setProperty("helidon.serialFilter.pattern", "javax.management.**;java.lang.**;java.rmi.**;javax.security.auth.Subject;!*"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found this advice on stackoverflow and it does seem to help and configure the JEP-290 filter, so it allows JMX. I can connect to the process with JVisualVM polyglot sampler now.
I'd say the first edit is fine on my computer.
It does feel like the first edit is taking considerably longer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
post merge comments
} | ||
if (!existsSync(ydocServerJar)) { | ||
const cwd = fileURLToPath(new URL('../..', import.meta.url)) | ||
const sbt = spawn('sbt', ['ydoc-server/assembly'], { cwd }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems like an unnecessary dependency. If someone forgot to build the jar, tough luck.
frgaalJavaCompilerSetting | ||
Compile / javaSource := baseDirectory.value / "generate-java" / "java" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why no longer under frgaal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It caused some compilation issues. Disabled because the project does not use Java 21 features.
var ydoc = Main.class.getResource(YDOC_SERVER_PATH); | ||
var contextBuilder = WebEnvironment.createContext().allowIO(IOAccess.ALL); | ||
|
||
Sampling.init(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, optional. Just moved the logic to a separate class.
log.debug(Arguments.toString(arguments)); | ||
|
||
return switch (command) { | ||
case RANDOM_UUID -> UUID.randomUUID().toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this a c&p mistake? There is no random-uuid
for AbortController
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll clean it up in the next PR
Addressing some PR comments, DRY.
Addressing some PR comments, DRY.
|
Pull Request Description
part of #7954
Important Notes
The workflow is:
$ npm install
-- just in case$ npm --workspace=enso-gui2 run build-ydoc-server-polyglot
-- build theydocServer.js
bundle$ sbt ydoc-server/assembly
-- build the ydoc server jarenv POLYGLOT_YDOC_SERVER=true npm --workspace=enso-gui2 run dev
-- run the dev server with the polyglot ydoc server. ProvidingPOLYGLOT_YDOC_SERVER_DEBUG=true
env variable enables the chrome debuggerChecklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
./run ide build
.