Skip to content
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

Replace Jackson serde #10035

Merged
merged 20 commits into from
Jun 11, 2024
Merged

Replace Jackson serde #10035

merged 20 commits into from
Jun 11, 2024

Conversation

hubertp
Copy link
Contributor

@hubertp hubertp commented May 22, 2024

Pull Request Description

JSON serialization setup between Language Server and Runtime is a major contributor to startup time. This PR experiments with an alternative implementation that remedies the problem.
The new serializer uses jsoniter-scala which by some accounts claims to be really fast. In our case, more importantly, we pay negligible cost of startup setup compared to Jackson which was horribly slow.

Important Notes

Before:
Screenshot from 2024-06-06 15-35-18
After:
Screenshot from 2024-06-06 15-35-02

Yes. About 0.8sec.

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.

1. Avoiding loading cats. It will we loaded later anyway but
   `catchNonFatal` is not worth it anyway
2. Avoid copying when reading all bytes from a file to compute digest of
   all files
@hubertp
Copy link
Contributor Author

hubertp commented May 22, 2024

Nit: what I really like about this library is that, when it works, the context of the parsing error is pretty visible:

com.github.plokhotnyuk.jsoniter_scala.core.JsonReaderException: expected '{' or null, offset: 0x0000018a, buf:
+----------+-------------------------------------------------+------------------+
|          |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f | 0123456789abcdef |
+----------+-------------------------------------------------+------------------+
| 00000160 | 72 6f 75 70 73 22 3a 5b 7b 22 67 72 6f 75 70 22 | roups":[{"group" |
| 00000170 | 3a 7b 22 6e 61 6d 65 22 3a 22 49 6e 70 75 74 22 | :{"name":"Input" |
| 00000180 | 7d 2c 22 63 6f 6c 6f 72 22 3a 22 6f 6b 6c 63 68 | },"color":"oklch |
| 00000190 | 28 30 2e 35 34 35 20 30 2e 31 34 20 31 37 30 29 | (0.545 0.14 170) |
| 000001a0 | 22 2c 22 65 78 70 6f 72 74 73 22 3a 5b 5d 7d 2c | ","exports":[]}, |
+----------+-------------------------------------------------+------------------+

@hubertp hubertp added the CI: Clean build required CI runners will be cleaned before and after this PR is built. label May 23, 2024
Turned out that one needs to separate definition site of the serializer
from usage so that macros can do the magic properly.
@hubertp hubertp added the CI: No changelog needed Do not require a changelog entry for this PR. label Jun 6, 2024
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't change dependencies of engine-common.

build.sbt Outdated Show resolved Hide resolved
When having nested option string values, decoders and encoders don't
seem to match under certain conditions. Added an option to skip the
values instead, which appears to remedy the problems.

Moving projects around to properly setup macros.
@hubertp hubertp marked this pull request as ready for review June 7, 2024 15:27
@hubertp hubertp changed the title Experiment with replacing Jackson serde Replace Jackson serde Jun 10, 2024
Copy link
Member

@Akirathan Akirathan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice startup speedup. I am just not sure what is the purpose of the new polyglot-api-macros project. It seems to me that the single source in that project can be merged into polyglot-api-serde project.

@@ -82,7 +85,14 @@ static final String computeDigestOfLibrarySources(List<SourceFile<TruffleFile>>
try {
var digest = messageDigest();
for (var source : pkgSources) {
digest.update(source.file().readAllBytes());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this change is not related to the json serialization? I am not sure whether this computeDigestOfLibrarySources is a useful method at all. It is used only by ImportExportCache. And when ImportExportCache [deserializes]

return new CachedBindings(libraryName, bindings, Optional.empty());
), it does not even read the sources from the cache. Maybe we should get rid of this method and compute digest in some other, more performant way in ImportExportCache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not related no. I just found out that this was taking unnecessary amount of time while profiling.

@@ -1478,6 +1478,32 @@ lazy val `polyglot-api` = project
.dependsOn(`logging-utils`)
.dependsOn(testkit % Test)

lazy val `polyglot-api-macros` = project
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of polyglot-api-macros project? Do I see correctly that it contains only single source SerdeConfig.scala? Shouldn't it be in polyglot-api-serde?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is necessary due to jsoniter-scala's usage of Scala macros. Macros have to be compiled separately from the usage site. Alternatively we could put everything into one module but then we would have to define some (simple) macros. I'd prefer to avoid that due to maintenance cost on our side.

Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we removing Jackson from our runtime.jar and runner.jar modules altogether?

build.sbt Outdated Show resolved Hide resolved
@@ -1,28 +1,7 @@
package org.enso.polyglot

import com.fasterxml.jackson.annotation.{JsonSubTypes, JsonTypeInfo}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing Jackson import is good. Do we also remove the Jackson dependency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did, see build.sbt.

@hubertp hubertp added the CI: Ready to merge This PR is eligible for automatic merge label Jun 11, 2024
@mergify mergify bot merged commit 4da5e61 into develop Jun 11, 2024
37 checks passed
@mergify mergify bot deleted the wip/hubert/9789-perf-nits branch June 11, 2024 15:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Clean build required CI runners will be cleaned before and after this PR is built. CI: No changelog needed Do not require a changelog entry for this PR. CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants