-
-
Notifications
You must be signed in to change notification settings - Fork 140
Remove unnecessary error generation when JsUndefined.asOpt is used #1112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| def error = err | ||
| def validationError = JsonValidationError(error) | ||
| override def toString = s"JsUndefined($err)" | ||
| override def asOpt[T](implicit fjs: Reads[T]): Option[T] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Make sure it's test covered
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What kind of test would you like me to add?
Testing that asOpt works as expected for both valid and invalid keys is already covered by other tests. Benchmarking to ensure performance stays within a certain threshold might be unreliable due to different test environments.
And I don’t have access to the intermediate object created inside asOpt to verify whether it was created or not in case of the older implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no direct test of JsUndefined whereas it can be easily done.
|
|
||
| "return None when calling asOpt on JsUndefined" in { | ||
| result.asOpt[Int] mustEqual None | ||
| result.asOpt[Int].mustEqual(None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is caused by our scalafmt config. We would need to change it to fix that.
Pull Request Checklist
Purpose
We discovered that in many cases, when JSON is parsed,
asOptis used to read an optional key. This results in a performance penalty because an error is generated each time, but it is not used in any way, as described in the documentation forasOpt.When
asOptis used on a missing key, it is called on theJsUndefinedobject. This triggers the execution of theasOptfunction inJsReadable, which performs unnecessary validation and ultimately returnsNoneafter constructing a large number of unnecessary strings.An example of this issue can be seen in the following flame graph:

A simple fix would be to always return
NonewhenasOptis called on theJsUndefinedobject.We tested the performance of the function on version
3.0.4witchScala 2.13.14andJava 21with and without the fix, and the results are as follows:Original version
Fixed version
As can easily be seen, the throughput increase is significant, and in our experience, in real-world applications, usually 70% of the time spent in asOpt will be saved in applications that frequently try to access missing keys.
The following code was used to test the throughput: