* 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.LocalDateTime
|
||||
import java.time.{ Duration => JDuration }
|
||||
import java.util
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import scala.concurrent.Await
|
||||
|
|
@ -51,11 +53,10 @@ object JacksonSerializationBench {
|
|||
final class TimeMessage(val duration: FiniteDuration, val date: LocalDateTime, val instant: Instant)
|
||||
extends TestMessage
|
||||
|
||||
// FIXME try with plain java classes (not case class)
|
||||
}
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
@BenchmarkMode(Array(Mode.Throughput))
|
||||
@Fork(2)
|
||||
@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())
|
||||
|
||||
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 serialization: Serialization = _
|
||||
|
||||
|
|
@ -133,7 +194,8 @@ class JacksonSerializationBench {
|
|||
loglevel = WARNING
|
||||
actor {
|
||||
serialization-bindings {
|
||||
"akka.serialization.jackson.JacksonSerializationBench$$TestMessage" = $serializerName
|
||||
"${classOf[TestMessage].getName}" = $serializerName
|
||||
"${classOf[JTestMessage].getName}" = $serializerName
|
||||
}
|
||||
}
|
||||
serialization.jackson {
|
||||
|
|
@ -185,6 +247,21 @@ class JacksonSerializationBench {
|
|||
serializeDeserialize(largeMsg)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
def jSmall(): JSmall = {
|
||||
serializeDeserialize(jSmallMsg1)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
def jMedium(): JMedium = {
|
||||
serializeDeserialize(jMediumMsg1)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
def jLarge(): JLarge = {
|
||||
serializeDeserialize(jLargeMsg)
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
def timeMessage(): TimeMessage = {
|
||||
serializeDeserialize(timeMsg)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ akka.serialization.jackson {
|
|||
jackson-modules += "com.fasterxml.jackson.datatype.jdk8.Jdk8Module"
|
||||
jackson-modules += "com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
|
|||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
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 final String name;
|
||||
public final ActorRef replyTo;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
package akka.serialization.jackson
|
||||
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import java.time.temporal.ChronoUnit
|
||||
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.node.IntNode
|
||||
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 org.scalatest.BeforeAndAfterAll
|
||||
import org.scalatest.Matchers
|
||||
|
|
@ -61,6 +62,7 @@ object ScalaTestMessages {
|
|||
final case class OptionCommand(maybe: Option[String]) extends TestMessage
|
||||
final case class BooleanCommand(published: Boolean) 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 CommandWithActorRef(name: String, replyTo: ActorRef) extends TestMessage
|
||||
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
|
||||
"not fail on unknown properties" in {
|
||||
val json = """{"name":"abc","name2":"def","name3":"ghi"}"""
|
||||
|
|
@ -251,7 +263,7 @@ class JacksonJsonSerializerSpec extends JacksonSerializerSpec("jackson-json") {
|
|||
bindingName: String,
|
||||
configuredModules: immutable.Seq[Module]): immutable.Seq[Module] =
|
||||
if (bindingName == "jackson-json") {
|
||||
configuredModules.filterNot(_.isInstanceOf[AfterburnerModule])
|
||||
configuredModules.filterNot(_.isInstanceOf[JavaTimeModule])
|
||||
} else
|
||||
super.overrideConfiguredModules(bindingName, configuredModules)
|
||||
}
|
||||
|
|
@ -262,15 +274,12 @@ class JacksonJsonSerializerSpec extends JacksonSerializerSpec("jackson-json") {
|
|||
.withSetup(JacksonObjectMapperProviderSetup(customJacksonObjectMapperFactory))
|
||||
.withSetup(BootstrapSetup(config))
|
||||
withSystem(setup) { sys =>
|
||||
val msg = SimpleCommand2("a", "b")
|
||||
val msg = InstantCommand(Instant.ofEpochMilli(1559907792075L))
|
||||
val json = serializeToJsonString(msg, sys)
|
||||
// using the custom ObjectMapper with pretty printing enabled
|
||||
val expected =
|
||||
"""|{
|
||||
| "name" : "a",
|
||||
| "name2" : "b"
|
||||
|}""".stripMargin
|
||||
json should ===(expected)
|
||||
// using the custom ObjectMapper with pretty printing enabled, and no JavaTimeModule
|
||||
json should include(""" "instant" : {""")
|
||||
json should include(""" "seconds" : 1559907792,""")
|
||||
json should include(""" "nanos" : 75000000,""")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ lazy val benchJmh = akkaModule("akka-bench-jmh")
|
|||
.dependsOn(Seq(actor, stream, streamTests, persistence, distributedData, jackson, testkit).map(
|
||||
_ % "compile->compile;compile->test"): _*)
|
||||
.settings(Dependencies.benchJmh)
|
||||
.settings(javacOptions += "-parameters") // for Jackson
|
||||
.enablePlugins(JmhPlugin, ScaladocNoVerificationOfDiagrams, NoPublish, CopyrightHeader)
|
||||
.disablePlugins(MimaPlugin, WhiteSourcePlugin, ValidatePullRequest, CopyrightHeaderInPr)
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ object Dependencies {
|
|||
val jacksonJsr310 = "com.fasterxml.jackson.datatype" % "jackson-datatype-jsr310" % 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 jacksonAfterburner = "com.fasterxml.jackson.module" % "jackson-module-afterburner" % jacksonVersion // ApacheV2
|
||||
val jacksonCbor = "com.fasterxml.jackson.dataformat" % "jackson-dataformat-cbor" % jacksonVersion // ApacheV2
|
||||
|
||||
object Docs {
|
||||
|
|
@ -243,7 +242,6 @@ object Dependencies {
|
|||
jacksonJdk8,
|
||||
jacksonJsr310,
|
||||
jacksonParameterNames,
|
||||
jacksonAfterburner,
|
||||
jacksonCbor,
|
||||
Test.junit,
|
||||
Test.scalatest.value)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue