diff --git a/benchmarks/src/main/scala/play/api/libs/json/JsLookupBench.scala b/benchmarks/src/main/scala/play/api/libs/json/JsLookupBench.scala new file mode 100644 index 000000000..7e116578f --- /dev/null +++ b/benchmarks/src/main/scala/play/api/libs/json/JsLookupBench.scala @@ -0,0 +1,35 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +package play.api.libs.json + +import org.openjdk.jmh.annotations._ + +import java.util.concurrent.TimeUnit + +@Warmup(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) +@State(Scope.Benchmark) +@BenchmarkMode(Array(Mode.Throughput)) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork( + jvmArgsAppend = + Array("-Xmx350m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:-BackgroundCompilation", "-XX:-TieredCompilation"), + value = 1 +) +class JsLookupBench { + @Param(Array("1", "20", "100")) + var size: Int = _ + private var jsObject: JsObject = _ + + @Setup def setup(): Unit = { + jsObject = JsObject(0.until(size).map(i => i.toString -> JsString(s"This is my content for index $i"))) + } + + @Benchmark + def goodLookup: Option[String] = (jsObject \ (size - 1).toString).asOpt[String] + + @Benchmark + def badLookup: Option[String] = (jsObject \ (size + 1).toString).asOpt[String] +} diff --git a/benchmarks/src/main/scala/play/api/libs/json/JsObjectBench.scala b/benchmarks/src/main/scala/play/api/libs/json/JsObjectBench.scala index 6f761d652..61fa3bfe7 100644 --- a/benchmarks/src/main/scala/play/api/libs/json/JsObjectBench.scala +++ b/benchmarks/src/main/scala/play/api/libs/json/JsObjectBench.scala @@ -1,3 +1,7 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + package play.api.libs.json import org.openjdk.jmh.annotations._ diff --git a/play-json/shared/src/main/scala/play/api/libs/json/JsLookup.scala b/play-json/shared/src/main/scala/play/api/libs/json/JsLookup.scala index 9168099b7..152b59afa 100644 --- a/play-json/shared/src/main/scala/play/api/libs/json/JsLookup.scala +++ b/play-json/shared/src/main/scala/play/api/libs/json/JsLookup.scala @@ -104,7 +104,9 @@ case class JsLookup(result: JsLookupResult) extends AnyVal { obj.underlying .get(fieldName) .map(JsDefined.apply) - .getOrElse(JsUndefined(s"'$fieldName' is undefined on object: $obj")) + .getOrElse( + JsUndefined(s"'$fieldName' is undefined on object. Available keys are ${obj.keys.mkString("'", "', '", "'")}") + ) case JsDefined(o) => JsUndefined(s"$o is not an object") case undef => undef