Optimize JsonObjectParser.isWhitespace by replacing Set.contains with match using table switch (#25260)

This commit is contained in:
Lukasz Stefaniak 2018-06-26 16:44:28 +02:00 committed by Arnout Engelen
parent 427124a531
commit b8230a38b7
3 changed files with 43 additions and 34 deletions

View file

@ -15,44 +15,37 @@ import org.openjdk.jmh.annotations._
@BenchmarkMode(Array(Mode.Throughput))
class JsonFramingBenchmark {
/*
Benchmark Mode Cnt Score Error Units
// old
JsonFramingBenchmark.collecting_1 thrpt 20 81.476 ± 14.793 ops/s
JsonFramingBenchmark.collecting_offer_5 thrpt 20 20.187 ± 2.291 ops/s
// new
JsonFramingBenchmark.counting_1 thrpt 20 10766.738 ± 1278.300 ops/s
JsonFramingBenchmark.counting_offer_5 thrpt 20 28798.255 ± 2670.163 ops/s
*/
val json =
ByteString(
"""{"fname":"Frank","name":"Smith","age":42,"id":1337,"boardMember":false}"""
)
val json5 =
ByteString(
"""|{"fname":"Frank","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Hank","name":"Smith","age":42,"id":1337,"boardMember":false}""".stripMargin
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Bob","name":"Smith","age":42,"id":1337,"boardMember":false},
|{"fname":"Hank","name":"Smith","age":42,"id":1337,"boardMember":false}""".stripMargin
)
val jsonLong =
ByteString(
s"""{"fname":"Frank","name":"Smith","age":42,"id":1337,"boardMember":false,"description":"${"a" * 1000000}"}"""
)
val bracket = new JsonObjectParser
@Setup(Level.Invocation)
def init(): Unit = {
bracket.offer(json)
}
@Benchmark
def counting_1: ByteString =
def counting_1: ByteString = {
bracket.offer(json)
bracket.poll().get
}
@Benchmark
@OperationsPerInvocation(5)
def counting_offer_5: ByteString = {
bracket.offer(json)
bracket.poll().get
bracket.offer(json5)
bracket.poll().get
bracket.poll().get
bracket.poll().get
@ -60,4 +53,10 @@ class JsonFramingBenchmark {
bracket.poll().get
}
@Benchmark
def counting_long_document: ByteString = {
bracket.offer(jsonLong)
bracket.poll().get
}
}

View file

@ -2,4 +2,11 @@
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.stream.javadsl.Flow.takeWhile$default$2")
# Wrong return type of FlowMonitorState.finished #24885
ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.stream.FlowMonitorState.finished")
ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.stream.FlowMonitorState.finished")
# JsonObjectParser.Whitespace removal #25260
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.stream.impl.JsonObjectParser.Whitespace")
ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.stream.impl.JsonObjectParser.Tab")
ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.stream.impl.JsonObjectParser.Space")
ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.stream.impl.JsonObjectParser.LineBreak2")
ProblemFilters.exclude[IncompatibleResultTypeProblem]("akka.stream.impl.JsonObjectParser.LineBreak")

View file

@ -23,15 +23,18 @@ import scala.annotation.switch
final val Backslash = '\\'.toByte
final val Comma = ','.toByte
final val LineBreak = '\n'.toByte
final val LineBreak2 = '\r'.toByte
final val Tab = '\t'.toByte
final val Space = ' '.toByte
final val LineBreak = 10 // '\n'
final val LineBreak2 = 13 // '\r'
final val Tab = 9 // '\t'
final val Space = 32 // ' '
final val Whitespace = Set(LineBreak, LineBreak2, Tab, Space)
def isWhitespace(input: Byte): Boolean =
Whitespace.contains(input)
def isWhitespace(b: Byte): Boolean = (b: @switch) match {
case Space true
case LineBreak true
case LineBreak2 true
case Tab true
case _ false
}
}