* remove Jackson afterburner, since no visible improvement #24155 * add back timeMessage benchmark * improve custom mapper test
This commit is contained in:
parent
fd1acb9326
commit
57fd889548
7 changed files with 231 additions and 18 deletions
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Lightbend Inc. <https://www.lightbend.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package akka.serialization.jackson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class JavaMessages {
|
||||||
|
interface JTestMessage {}
|
||||||
|
|
||||||
|
public static class JSmall implements JTestMessage {
|
||||||
|
public final String name;
|
||||||
|
public final int num;
|
||||||
|
|
||||||
|
public JSmall(String name, int num) {
|
||||||
|
this.name = name;
|
||||||
|
this.num = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JMedium implements JTestMessage {
|
||||||
|
public final String field1;
|
||||||
|
public final String field2;
|
||||||
|
public final String field3;
|
||||||
|
public final int num1;
|
||||||
|
public final int num2;
|
||||||
|
public final int num3;
|
||||||
|
public final boolean flag1;
|
||||||
|
public final boolean flag2;
|
||||||
|
public final Duration duration;
|
||||||
|
|
||||||
|
public final LocalDateTime date;
|
||||||
|
public final Instant instant;
|
||||||
|
public final JSmall nested1;
|
||||||
|
public final JSmall nested2;
|
||||||
|
public final JSmall nested3;
|
||||||
|
|
||||||
|
public JMedium(
|
||||||
|
String field1,
|
||||||
|
String field2,
|
||||||
|
String field3,
|
||||||
|
int num1,
|
||||||
|
int num2,
|
||||||
|
int num3,
|
||||||
|
boolean flag1,
|
||||||
|
boolean flag2,
|
||||||
|
Duration duration,
|
||||||
|
LocalDateTime date,
|
||||||
|
Instant instant,
|
||||||
|
JSmall nested1,
|
||||||
|
JSmall nested2,
|
||||||
|
JSmall nested3) {
|
||||||
|
this.field1 = field1;
|
||||||
|
this.field2 = field2;
|
||||||
|
this.field3 = field3;
|
||||||
|
this.num1 = num1;
|
||||||
|
this.num2 = num2;
|
||||||
|
this.num3 = num3;
|
||||||
|
this.flag1 = flag1;
|
||||||
|
this.flag2 = flag2;
|
||||||
|
this.duration = duration;
|
||||||
|
this.date = date;
|
||||||
|
this.instant = instant;
|
||||||
|
this.nested1 = nested1;
|
||||||
|
this.nested2 = nested2;
|
||||||
|
this.nested3 = nested3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JLarge implements JTestMessage {
|
||||||
|
public final JMedium nested1;
|
||||||
|
public final JMedium nested2;
|
||||||
|
public final JMedium nested3;
|
||||||
|
public final List<JMedium> list;
|
||||||
|
public final Map<String, JMedium> map;
|
||||||
|
|
||||||
|
public JLarge(
|
||||||
|
JMedium nested1,
|
||||||
|
JMedium nested2,
|
||||||
|
JMedium nested3,
|
||||||
|
List<JMedium> list,
|
||||||
|
Map<String, JMedium> map) {
|
||||||
|
this.nested1 = nested1;
|
||||||
|
this.nested2 = nested2;
|
||||||
|
this.nested3 = nested3;
|
||||||
|
this.list = list;
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,8 @@ package akka.serialization.jackson
|
||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
import java.time.{ Duration => JDuration }
|
||||||
|
import java.util
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import scala.concurrent.Await
|
import scala.concurrent.Await
|
||||||
|
|
@ -51,11 +53,10 @@ object JacksonSerializationBench {
|
||||||
final class TimeMessage(val duration: FiniteDuration, val date: LocalDateTime, val instant: Instant)
|
final class TimeMessage(val duration: FiniteDuration, val date: LocalDateTime, val instant: Instant)
|
||||||
extends TestMessage
|
extends TestMessage
|
||||||
|
|
||||||
// FIXME try with plain java classes (not case class)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||||
@BenchmarkMode(Array(Mode.Throughput))
|
@BenchmarkMode(Array(Mode.Throughput))
|
||||||
@Fork(2)
|
@Fork(2)
|
||||||
@Warmup(iterations = 4)
|
@Warmup(iterations = 4)
|
||||||
|
|
@ -120,6 +121,66 @@ class JacksonSerializationBench {
|
||||||
|
|
||||||
val timeMsg = new TimeMessage(5.seconds, LocalDateTime.of(2019, 4, 29, 23, 15, 3, 12345), Instant.now())
|
val timeMsg = new TimeMessage(5.seconds, LocalDateTime.of(2019, 4, 29, 23, 15, 3, 12345), Instant.now())
|
||||||
|
|
||||||
|
import JavaMessages._
|
||||||
|
val jSmallMsg1 = new JSmall("abc", 17)
|
||||||
|
val jSmallMsg2 = new JSmall("def", 18)
|
||||||
|
val jSmallMsg3 = new JSmall("ghi", 19)
|
||||||
|
val jMediumMsg1 = new JMedium(
|
||||||
|
"abc",
|
||||||
|
"def",
|
||||||
|
"ghi",
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
JDuration.ofSeconds(5),
|
||||||
|
LocalDateTime.of(2019, 4, 29, 23, 15, 3, 12345),
|
||||||
|
Instant.now(),
|
||||||
|
jSmallMsg1,
|
||||||
|
jSmallMsg2,
|
||||||
|
jSmallMsg3)
|
||||||
|
val jMediumMsg2 = new JMedium(
|
||||||
|
"ABC",
|
||||||
|
"DEF",
|
||||||
|
"GHI",
|
||||||
|
10,
|
||||||
|
20,
|
||||||
|
30,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
JDuration.ofMillis(5),
|
||||||
|
LocalDateTime.of(2019, 4, 29, 23, 15, 4, 12345),
|
||||||
|
Instant.now(),
|
||||||
|
jSmallMsg1,
|
||||||
|
jSmallMsg2,
|
||||||
|
jSmallMsg3)
|
||||||
|
val jMediumMsg3 = new JMedium(
|
||||||
|
"abcABC",
|
||||||
|
"defDEF",
|
||||||
|
"ghiGHI",
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
300,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
JDuration.ofMillis(200),
|
||||||
|
LocalDateTime.of(2019, 4, 29, 23, 15, 5, 12345),
|
||||||
|
Instant.now(),
|
||||||
|
jSmallMsg1,
|
||||||
|
jSmallMsg2,
|
||||||
|
jSmallMsg3)
|
||||||
|
val jMap = new util.HashMap[String, JMedium]()
|
||||||
|
jMap.put("a", jMediumMsg1)
|
||||||
|
jMap.put("b", jMediumMsg2)
|
||||||
|
jMap.put("c", jMediumMsg3)
|
||||||
|
val jLargeMsg = new JLarge(
|
||||||
|
jMediumMsg1,
|
||||||
|
jMediumMsg2,
|
||||||
|
jMediumMsg3,
|
||||||
|
java.util.Arrays.asList(jMediumMsg1, jMediumMsg2, jMediumMsg3),
|
||||||
|
jMap)
|
||||||
|
|
||||||
var system: ActorSystem = _
|
var system: ActorSystem = _
|
||||||
var serialization: Serialization = _
|
var serialization: Serialization = _
|
||||||
|
|
||||||
|
|
@ -133,7 +194,8 @@ class JacksonSerializationBench {
|
||||||
loglevel = WARNING
|
loglevel = WARNING
|
||||||
actor {
|
actor {
|
||||||
serialization-bindings {
|
serialization-bindings {
|
||||||
"akka.serialization.jackson.JacksonSerializationBench$$TestMessage" = $serializerName
|
"${classOf[TestMessage].getName}" = $serializerName
|
||||||
|
"${classOf[JTestMessage].getName}" = $serializerName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serialization.jackson {
|
serialization.jackson {
|
||||||
|
|
@ -185,6 +247,21 @@ class JacksonSerializationBench {
|
||||||
serializeDeserialize(largeMsg)
|
serializeDeserialize(largeMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
def jSmall(): JSmall = {
|
||||||
|
serializeDeserialize(jSmallMsg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
def jMedium(): JMedium = {
|
||||||
|
serializeDeserialize(jMediumMsg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
def jLarge(): JLarge = {
|
||||||
|
serializeDeserialize(jLargeMsg)
|
||||||
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
def timeMessage(): TimeMessage = {
|
def timeMessage(): TimeMessage = {
|
||||||
serializeDeserialize(timeMsg)
|
serializeDeserialize(timeMsg)
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,6 @@ akka.serialization.jackson {
|
||||||
jackson-modules += "com.fasterxml.jackson.datatype.jdk8.Jdk8Module"
|
jackson-modules += "com.fasterxml.jackson.datatype.jdk8.Jdk8Module"
|
||||||
jackson-modules += "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"
|
jackson-modules += "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"
|
||||||
jackson-modules += "com.fasterxml.jackson.module.scala.DefaultScalaModule"
|
jackson-modules += "com.fasterxml.jackson.module.scala.DefaultScalaModule"
|
||||||
jackson-modules += "com.fasterxml.jackson.module.afterburner.AfterburnerModule"
|
|
||||||
#jackson-modules += "com.fasterxml.jackson.datatype.pcollections.PCollectionsModule"
|
|
||||||
#jackson-modules += "com.fasterxml.jackson.datatype.guava.GuavaModule"
|
|
||||||
}
|
}
|
||||||
#//#jackson-modules
|
#//#jackson-modules
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
@ -204,6 +205,39 @@ public interface JavaTestMessages {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class InstantCommand implements TestMessage {
|
||||||
|
public final Instant instant;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public InstantCommand(Instant instant) {
|
||||||
|
this.instant = instant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant getInstant() {
|
||||||
|
return instant;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
InstantCommand that = (InstantCommand) o;
|
||||||
|
|
||||||
|
return instant.equals(that.instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return instant.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "InstantCommand{" + "instant=" + instant + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class CommandWithActorRef implements TestMessage {
|
public class CommandWithActorRef implements TestMessage {
|
||||||
public final String name;
|
public final String name;
|
||||||
public final ActorRef replyTo;
|
public final ActorRef replyTo;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package akka.serialization.jackson
|
package akka.serialization.jackson
|
||||||
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
|
|
@ -39,7 +40,7 @@ import com.fasterxml.jackson.databind.SerializationFeature
|
||||||
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException
|
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException
|
||||||
import com.fasterxml.jackson.databind.node.IntNode
|
import com.fasterxml.jackson.databind.node.IntNode
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode
|
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||||
import com.fasterxml.jackson.module.afterburner.AfterburnerModule
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import org.scalatest.BeforeAndAfterAll
|
import org.scalatest.BeforeAndAfterAll
|
||||||
import org.scalatest.Matchers
|
import org.scalatest.Matchers
|
||||||
|
|
@ -61,6 +62,7 @@ object ScalaTestMessages {
|
||||||
final case class OptionCommand(maybe: Option[String]) extends TestMessage
|
final case class OptionCommand(maybe: Option[String]) extends TestMessage
|
||||||
final case class BooleanCommand(published: Boolean) extends TestMessage
|
final case class BooleanCommand(published: Boolean) extends TestMessage
|
||||||
final case class TimeCommand(timestamp: LocalDateTime, duration: FiniteDuration) extends TestMessage
|
final case class TimeCommand(timestamp: LocalDateTime, duration: FiniteDuration) extends TestMessage
|
||||||
|
final case class InstantCommand(instant: Instant) extends TestMessage
|
||||||
final case class CollectionsCommand(strings: List[String], objects: Vector[SimpleCommand]) extends TestMessage
|
final case class CollectionsCommand(strings: List[String], objects: Vector[SimpleCommand]) extends TestMessage
|
||||||
final case class CommandWithActorRef(name: String, replyTo: ActorRef) extends TestMessage
|
final case class CommandWithActorRef(name: String, replyTo: ActorRef) extends TestMessage
|
||||||
final case class CommandWithTypedActorRef(name: String, replyTo: akka.actor.typed.ActorRef[String])
|
final case class CommandWithTypedActorRef(name: String, replyTo: akka.actor.typed.ActorRef[String])
|
||||||
|
|
@ -209,6 +211,16 @@ class JacksonJsonSerializerSpec extends JacksonSerializerSpec("jackson-json") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"serialize Instant as text with ISO-8601 date format (default)" in {
|
||||||
|
val msg = new InstantCommand(Instant.ofEpochMilli(1559907792075L))
|
||||||
|
val json = serializeToJsonString(msg)
|
||||||
|
val expected = """{"instant":"2019-06-07T11:43:12.075Z"}"""
|
||||||
|
json should ===(expected)
|
||||||
|
|
||||||
|
// and full round trip
|
||||||
|
checkSerialization(msg)
|
||||||
|
}
|
||||||
|
|
||||||
// FAIL_ON_UNKNOWN_PROPERTIES = off is default in reference.conf
|
// FAIL_ON_UNKNOWN_PROPERTIES = off is default in reference.conf
|
||||||
"not fail on unknown properties" in {
|
"not fail on unknown properties" in {
|
||||||
val json = """{"name":"abc","name2":"def","name3":"ghi"}"""
|
val json = """{"name":"abc","name2":"def","name3":"ghi"}"""
|
||||||
|
|
@ -251,7 +263,7 @@ class JacksonJsonSerializerSpec extends JacksonSerializerSpec("jackson-json") {
|
||||||
bindingName: String,
|
bindingName: String,
|
||||||
configuredModules: immutable.Seq[Module]): immutable.Seq[Module] =
|
configuredModules: immutable.Seq[Module]): immutable.Seq[Module] =
|
||||||
if (bindingName == "jackson-json") {
|
if (bindingName == "jackson-json") {
|
||||||
configuredModules.filterNot(_.isInstanceOf[AfterburnerModule])
|
configuredModules.filterNot(_.isInstanceOf[JavaTimeModule])
|
||||||
} else
|
} else
|
||||||
super.overrideConfiguredModules(bindingName, configuredModules)
|
super.overrideConfiguredModules(bindingName, configuredModules)
|
||||||
}
|
}
|
||||||
|
|
@ -262,15 +274,12 @@ class JacksonJsonSerializerSpec extends JacksonSerializerSpec("jackson-json") {
|
||||||
.withSetup(JacksonObjectMapperProviderSetup(customJacksonObjectMapperFactory))
|
.withSetup(JacksonObjectMapperProviderSetup(customJacksonObjectMapperFactory))
|
||||||
.withSetup(BootstrapSetup(config))
|
.withSetup(BootstrapSetup(config))
|
||||||
withSystem(setup) { sys =>
|
withSystem(setup) { sys =>
|
||||||
val msg = SimpleCommand2("a", "b")
|
val msg = InstantCommand(Instant.ofEpochMilli(1559907792075L))
|
||||||
val json = serializeToJsonString(msg, sys)
|
val json = serializeToJsonString(msg, sys)
|
||||||
// using the custom ObjectMapper with pretty printing enabled
|
// using the custom ObjectMapper with pretty printing enabled, and no JavaTimeModule
|
||||||
val expected =
|
json should include(""" "instant" : {""")
|
||||||
"""|{
|
json should include(""" "seconds" : 1559907792,""")
|
||||||
| "name" : "a",
|
json should include(""" "nanos" : 75000000,""")
|
||||||
| "name2" : "b"
|
|
||||||
|}""".stripMargin
|
|
||||||
json should ===(expected)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ lazy val benchJmh = akkaModule("akka-bench-jmh")
|
||||||
.dependsOn(Seq(actor, stream, streamTests, persistence, distributedData, jackson, testkit).map(
|
.dependsOn(Seq(actor, stream, streamTests, persistence, distributedData, jackson, testkit).map(
|
||||||
_ % "compile->compile;compile->test"): _*)
|
_ % "compile->compile;compile->test"): _*)
|
||||||
.settings(Dependencies.benchJmh)
|
.settings(Dependencies.benchJmh)
|
||||||
|
.settings(javacOptions += "-parameters") // for Jackson
|
||||||
.enablePlugins(JmhPlugin, ScaladocNoVerificationOfDiagrams, NoPublish, CopyrightHeader)
|
.enablePlugins(JmhPlugin, ScaladocNoVerificationOfDiagrams, NoPublish, CopyrightHeader)
|
||||||
.disablePlugins(MimaPlugin, WhiteSourcePlugin, ValidatePullRequest, CopyrightHeaderInPr)
|
.disablePlugins(MimaPlugin, WhiteSourcePlugin, ValidatePullRequest, CopyrightHeaderInPr)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,6 @@ object Dependencies {
|
||||||
val jacksonJsr310 = "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % jacksonVersion // ApacheV2
|
val jacksonJsr310 = "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % jacksonVersion // ApacheV2
|
||||||
val jacksonScala = "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion // ApacheV2
|
val jacksonScala = "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion // ApacheV2
|
||||||
val jacksonParameterNames = "com.fasterxml.jackson.module" % "jackson-module-parameter-names" % jacksonVersion // ApacheV2
|
val jacksonParameterNames = "com.fasterxml.jackson.module" % "jackson-module-parameter-names" % jacksonVersion // ApacheV2
|
||||||
val jacksonAfterburner = "com.fasterxml.jackson.module" % "jackson-module-afterburner" % jacksonVersion // ApacheV2
|
|
||||||
val jacksonCbor = "com.fasterxml.jackson.dataformat" % "jackson-dataformat-cbor" % jacksonVersion // ApacheV2
|
val jacksonCbor = "com.fasterxml.jackson.dataformat" % "jackson-dataformat-cbor" % jacksonVersion // ApacheV2
|
||||||
|
|
||||||
object Docs {
|
object Docs {
|
||||||
|
|
@ -243,7 +242,6 @@ object Dependencies {
|
||||||
jacksonJdk8,
|
jacksonJdk8,
|
||||||
jacksonJsr310,
|
jacksonJsr310,
|
||||||
jacksonParameterNames,
|
jacksonParameterNames,
|
||||||
jacksonAfterburner,
|
|
||||||
jacksonCbor,
|
jacksonCbor,
|
||||||
Test.junit,
|
Test.junit,
|
||||||
Test.scalatest.value)
|
Test.scalatest.value)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue