enso-org / enso

Enso Analytics is a self-service data prep and analysis platform designed for data teams.
https://ensoanalytics.com
Apache License 2.0
7.39k stars 323 forks source link

Schedule initialization of JS context in a separate thread after main compiler's initialization is done #5643

Closed hubertp closed 1 year ago

hubertp commented 1 year ago

On a first attempt to parse JS code, Truffle will attempt to get initialized context for it. The initialization is a one-off, expensive, operation that we could potentially pro-actively schedule after the compiler is initialized but before the first compilation is triggered.

The screenshots illustrates precious time that is lost waiting for the context to be initialized (as invoked in ForeignNode#parseJs) Screenshot from 2023-02-12 15-59-45

enso-bot[bot] commented 1 year ago

Jaroslav Tulach reports a new STANDUP for yesterday (2023-02-14):

Progress: - plannng meeting It should be finished by 2023-02-17.

Next Day: Interop. Stability. Performance.

enso-bot[bot] commented 1 year ago

Jaroslav Tulach reports a new STANDUP for yesterday (2023-02-15):

Progress: 1:1 meetings It should be finished by 2023-02-17.

Next Day: Interop. Stability. Performance.

JaroslavTulach commented 1 year ago

Playing with an idea to warm up the JavaScript. Let's have a pre-initialize option:

enso$ git diff engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala engine/polyglot-api/src/main/java/org/enso/polyglot/RuntimeOptions.java
diff --git a/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala b/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala
index 5f03f4da2..ca6eb5ac8 100644
--- a/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala
+++ b/engine/language-server/src/main/scala/org/enso/languageserver/boot/MainModule.scala
@@ -274,7 +274,7 @@ class MainModule(serverConfig: LanguageServerConfig, logLevel: LogLevel) {
   val stdInSink = new ObservableOutputStream
   val stdIn     = new ObservablePipedInputStream(stdInSink)

-  val context = Context
+  val context: Context = Context
     .newBuilder()
     .allowAllAccess(true)
     .allowHostAccess(new HostAccessFactory().allWithTypeMapping())
@@ -292,6 +292,7 @@ class MainModule(serverConfig: LanguageServerConfig, logLevel: LogLevel) {
       RuntimeServerInfo.JOB_PARALLELISM_OPTION,
       Runtime.getRuntime.availableProcessors().toString
     )
+    .option(RuntimeOptions.PREINITIALIZE, "js")
     .out(stdOut)
     .err(stdErr)
     .in(stdIn)
diff --git a/engine/polyglot-api/src/main/java/org/enso/polyglot/RuntimeOptions.java b/engine/polyglot-api/src/main/java/org/enso/polyglot/RuntimeOptions.java
index a1f92bf4d..6adcfc7f4 100644
--- a/engine/polyglot-api/src/main/java/org/enso/polyglot/RuntimeOptions.java
+++ b/engine/polyglot-api/src/main/java/org/enso/polyglot/RuntimeOptions.java
@@ -71,6 +71,10 @@ public class RuntimeOptions {
       OptionDescriptor.newBuilder(EDITION_OVERRIDE_KEY, EDITION_OVERRIDE).build();

   public static final String DISABLE_IR_CACHES = optionName("disableIrCaches");
+  public static final String PREINITIALIZE = optionName("preinitialize");
+  public static final OptionKey<String> PREINITIALIZE_KEY = new OptionKey<>("");
+  private static final OptionDescriptor PREINITIALIZE_DESCRIPTOR =
+      OptionDescriptor.newBuilder(PREINITIALIZE_KEY, PREINITIALIZE).build();
   public static final OptionKey<Boolean> DISABLE_IR_CACHES_KEY = new OptionKey<>(false);
   private static final OptionDescriptor DISABLE_IR_CACHES_DESCRIPTOR =
       OptionDescriptor.newBuilder(DISABLE_IR_CACHES_KEY, DISABLE_IR_CACHES).build();
@@ -115,6 +119,7 @@ public class RuntimeOptions {
               EDITION_OVERRIDE_DESCRIPTOR,
               INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_DESCRIPTOR,
               DISABLE_IR_CACHES_DESCRIPTOR,
+              PREINITIALIZE_DESCRIPTOR,
               WAIT_FOR_PENDING_SERIALIZATION_JOBS_DESCRIPTOR,
               USE_GLOBAL_IR_CACHE_LOCATION_DESCRIPTOR,
               ENABLE_EXECUTION_TIMER_DESCRIPTOR));

and then let's handle it when EnsoLanguage.initializeContext is called. I would probably call into EpbLanguage and try to initializeLanguage("js").

enso-bot[bot] commented 1 year ago

Jaroslav Tulach reports a new STANDUP for yesterday (2023-02-16):

Progress:

Next Day: Pre-initialize JavaScript.

JaroslavTulach commented 1 year ago

With #5680 fixes I am seeing following results. The first "parsing of JavaScript" file went down to 119ms: 119ms in parsing the initialization of the JavaScript has moved from that moment to 3rd second of initialization and is done in a background thread 470ms

It runs in parallel with other initialization tasks. Following picture shows that at the same time when JavaScript is being initialized we also initialize Endpoint.sendToClient & etc. - e.g. the benefit of parallel initialization shall deliver an improment:

Endpoint.sendToClient

Presumably almost all of the JavaScript initialization time.