remove Jackson afterburner, since no visible improvement #24155 (#27064)

* remove Jackson afterburner, since no visible improvement #24155

* add back timeMessage benchmark

* improve custom mapper test
This commit is contained in:
Patrik Nordwall 2019-06-13 21:53:21 +02:00 committed by GitHub
parent fd1acb9326
commit 57fd889548
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 231 additions and 18 deletions

View file

@ -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;
}
}
}

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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)
} }
} }

View file

@ -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)

View file

@ -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)