From d86c6c472cf9bde95a8c3b640858dd8a8951158b Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Mon, 8 Jan 2024 13:17:37 +0100 Subject: [PATCH] Replace Jackson library by simple data I/O streams (#8693) --- build.sbt | 3 +- .../org/enso/interpreter/caches/Cache.java | 13 +++-- .../interpreter/caches/ImportExportCache.java | 52 +++++++++-------- .../enso/interpreter/caches/ModuleCache.java | 57 ++++++++++--------- .../interpreter/caches/SuggestionsCache.java | 49 ++++++++-------- 5 files changed, 91 insertions(+), 83 deletions(-) diff --git a/build.sbt b/build.sbt index f4ee0340a16..1ec7a566aa8 100644 --- a/build.sbt +++ b/build.sbt @@ -1557,7 +1557,7 @@ lazy val runtime = (project in file("engine/runtime")) ), // show timings for individual tests scalacOptions += "-Ymacro-annotations", scalacOptions ++= Seq("-Ypatmat-exhaust-depth", "off"), - libraryDependencies ++= jmh ++ jaxb ++ circe ++ GraalVM.langsPkgs ++ Seq( + libraryDependencies ++= jmh ++ jaxb ++ GraalVM.langsPkgs ++ Seq( "org.apache.commons" % "commons-lang3" % commonsLangVersion, "org.apache.tika" % "tika-core" % tikaVersion, "org.graalvm.polyglot" % "polyglot" % graalMavenPackagesVersion % "provided", @@ -1571,7 +1571,6 @@ lazy val runtime = (project in file("engine/runtime")) "org.scalactic" %% "scalactic" % scalacticVersion % Test, "org.scalatest" %% "scalatest" % scalatestVersion % Test, "org.graalvm.truffle" % "truffle-api" % graalMavenPackagesVersion % Benchmark, - "org.typelevel" %% "cats-core" % catsVersion, "junit" % "junit" % junitVersion % Test, "com.github.sbt" % "junit-interface" % junitIfVersion % Test, "org.hamcrest" % "hamcrest-all" % hamcrestVersion % Test, diff --git a/engine/runtime/src/main/java/org/enso/interpreter/caches/Cache.java b/engine/runtime/src/main/java/org/enso/interpreter/caches/Cache.java index 0e3c4ca579d..b66e0e394b3 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/caches/Cache.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/caches/Cache.java @@ -4,8 +4,6 @@ import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLogger; import java.io.IOException; import java.io.OutputStream; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.StandardOpenOption; @@ -175,8 +173,10 @@ public abstract class Cache { * @param blobDigest digest of serialized data * @param entry data to serialize * @return raw bytes representing serialized metadata + * @throws java.io.IOException in case of I/O error */ - protected abstract byte[] metadata(String sourceDigest, String blobDigest, T entry); + protected abstract byte[] metadata(String sourceDigest, String blobDigest, T entry) + throws IOException; /** * Loads cache for this data, if possible. @@ -333,9 +333,12 @@ public abstract class Cache { * De-serializes raw bytes to data's metadata. * * @param bytes raw bytes representing metadata + * @param logger logger to use * @return non-empty metadata, if de-serialization was successful + * @throws IOException in case of I/O error */ - protected abstract Optional metadataFromBytes(byte[] bytes, TruffleLogger logger); + protected abstract Optional metadataFromBytes(byte[] bytes, TruffleLogger logger) + throws IOException; /** * Compute digest of cache's data @@ -509,8 +512,6 @@ public abstract class Cache { } } - protected static final Charset metadataCharset = StandardCharsets.UTF_8; - /** * Roots encapsulates two possible locations where caches can be stored. * diff --git a/engine/runtime/src/main/java/org/enso/interpreter/caches/ImportExportCache.java b/engine/runtime/src/main/java/org/enso/interpreter/caches/ImportExportCache.java index 8fe097d659e..2299e24ad12 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/caches/ImportExportCache.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/caches/ImportExportCache.java @@ -1,11 +1,12 @@ package org.enso.interpreter.caches; import buildinfo.Info; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLogger; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; import java.util.List; import java.util.Optional; @@ -40,14 +41,9 @@ public final class ImportExportCache } @Override - protected byte[] metadata(String sourceDigest, String blobDigest, CachedBindings entry) { - try { - return objectMapper - .writeValueAsString(new Metadata(sourceDigest, blobDigest)) - .getBytes(metadataCharset); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } + protected byte[] metadata(String sourceDigest, String blobDigest, CachedBindings entry) + throws IOException { + return new Metadata(sourceDigest, blobDigest).toBytes(); } @Override @@ -60,15 +56,9 @@ public final class ImportExportCache } @Override - protected Optional metadataFromBytes(byte[] bytes, TruffleLogger logger) { - var maybeJsonString = new String(bytes, Cache.metadataCharset); - var mapper = new ObjectMapper(); - try { - return Optional.of(objectMapper.readValue(maybeJsonString, ImportExportCache.Metadata.class)); - } catch (JsonProcessingException e) { - logger.log(logLevel, "Failed to deserialize library's metadata.", e); - return Optional.empty(); - } + protected Optional metadataFromBytes(byte[] bytes, TruffleLogger logger) + throws IOException { + return Optional.of(Metadata.read(bytes)); } @Override @@ -172,16 +162,28 @@ public final class ImportExportCache MapToBindings bindings, Optional>> sources) {} - public record Metadata( - @JsonProperty("source_hash") String sourceHash, @JsonProperty("blob_hash") String blobHash) - implements Cache.Metadata {} + public record Metadata(String sourceHash, String blobHash) implements Cache.Metadata { + byte[] toBytes() throws IOException { + try (var os = new ByteArrayOutputStream(); + var dos = new DataOutputStream(os)) { + dos.writeUTF(sourceHash()); + dos.writeUTF(blobHash()); + return os.toByteArray(); + } + } + + static Metadata read(byte[] arr) throws IOException { + try (var is = new ByteArrayInputStream(arr); + var dis = new DataInputStream(is)) { + return new Metadata(dis.readUTF(), dis.readUTF()); + } + } + } private static final String bindingsCacheDataExtension = ".bindings"; private static final String bindingsCacheMetadataExtension = ".bindings.meta"; - private static final ObjectMapper objectMapper = new ObjectMapper(); - @Persistable(clazz = BindingsMap.PolyglotSymbol.class, id = 33006) @Persistable( clazz = org.enso.compiler.data.BindingsMap$ModuleReference$Abstract.class, diff --git a/engine/runtime/src/main/java/org/enso/interpreter/caches/ModuleCache.java b/engine/runtime/src/main/java/org/enso/interpreter/caches/ModuleCache.java index 566c9898203..896733e8a32 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/caches/ModuleCache.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/caches/ModuleCache.java @@ -1,12 +1,14 @@ package org.enso.interpreter.caches; import buildinfo.Info; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.source.Source; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Optional; @@ -33,13 +35,9 @@ public final class ModuleCache extends Cache metadataFromBytes(byte[] bytes, TruffleLogger logger) { - var maybeJsonString = new String(bytes, Cache.metadataCharset); - try { - return Optional.of(objectMapper.readValue(maybeJsonString, Metadata.class)); - } catch (JsonProcessingException e) { - logger.log(logLevel, "Failed to deserialize module's metadata.", e); - return Optional.empty(); - } + protected Optional metadataFromBytes(byte[] bytes, TruffleLogger logger) + throws IOException { + return Optional.of(Metadata.read(bytes)); } private Optional computeDigestOfModuleSources(Source source) { @@ -85,7 +78,7 @@ public final class ModuleCache extends Cache T raise(Class cls, Exception e) throws T { throw (T) e; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/caches/SuggestionsCache.java b/engine/runtime/src/main/java/org/enso/interpreter/caches/SuggestionsCache.java index 248739c19e6..92088ee2d05 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/caches/SuggestionsCache.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/caches/SuggestionsCache.java @@ -1,13 +1,12 @@ package org.enso.interpreter.caches; import buildinfo.Info; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLogger; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -27,8 +26,6 @@ public final class SuggestionsCache private static final String SUGGESTIONS_CACHE_DATA_EXTENSION = ".suggestions"; private static final String SUGGESTIONS_CACHE_METADATA_EXTENSION = ".suggestions.meta"; - private static final ObjectMapper objectMapper = new ObjectMapper(); - final LibraryName libraryName; public SuggestionsCache(LibraryName libraryName) { @@ -40,14 +37,9 @@ public final class SuggestionsCache } @Override - protected byte[] metadata(String sourceDigest, String blobDigest, CachedSuggestions entry) { - try { - return objectMapper - .writeValueAsString(new Metadata(sourceDigest, blobDigest)) - .getBytes(metadataCharset); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } + protected byte[] metadata(String sourceDigest, String blobDigest, CachedSuggestions entry) + throws IOException { + return new Metadata(sourceDigest, blobDigest).toBytes(); } @Override @@ -65,14 +57,9 @@ public final class SuggestionsCache } @Override - protected Optional metadataFromBytes(byte[] bytes, TruffleLogger logger) { - var maybeJsonString = new String(bytes, Cache.metadataCharset); - try { - return Optional.of(objectMapper.readValue(maybeJsonString, SuggestionsCache.Metadata.class)); - } catch (JsonProcessingException e) { - logger.log(logLevel, "Failed to deserialize suggestions' metadata.", e); - return Optional.empty(); - } + protected Optional metadataFromBytes(byte[] bytes, TruffleLogger logger) + throws IOException { + return Optional.of(Metadata.read(bytes)); } @Override @@ -173,7 +160,21 @@ public final class SuggestionsCache } } - record Metadata( - @JsonProperty("source_hash") String sourceHash, @JsonProperty("blob_hash") String blobHash) - implements Cache.Metadata {} + record Metadata(String sourceHash, String blobHash) implements Cache.Metadata { + byte[] toBytes() throws IOException { + try (var os = new ByteArrayOutputStream(); + var dos = new DataOutputStream(os)) { + dos.writeUTF(sourceHash()); + dos.writeUTF(blobHash()); + return os.toByteArray(); + } + } + + static Metadata read(byte[] arr) throws IOException { + try (var is = new ByteArrayInputStream(arr); + var dis = new DataInputStream(is)) { + return new Metadata(dis.readUTF(), dis.readUTF()); + } + } + } }