-
-
Notifications
You must be signed in to change notification settings - Fork 135
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
Remove unnecessary error generation when JsUndefined.asOpt is used #1112
base: main
Are you sure you want to change the base?
Conversation
…e asOpt function was used
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.
@@ -21,7 +21,7 @@ class JsLookupSpec extends AnyWordSpec with Matchers { | |||
} | |||
|
|||
"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
Pull Request Checklist
Purpose
We discovered that in many cases, when JSON is parsed,
asOpt
is 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
asOpt
is used on a missing key, it is called on theJsUndefined
object. This triggers the execution of theasOpt
function inJsReadable
, which performs unnecessary validation and ultimately returnsNone
after constructing a large number of unnecessary strings.An example of this issue can be seen in the following flame graph:
![image](https://private-user-images.githubusercontent.com/33125438/396634268-d36ae471-2e31-4132-a34b-701fa37ce460.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2ODU2NjMsIm5iZiI6MTczOTY4NTM2MywicGF0aCI6Ii8zMzEyNTQzOC8zOTY2MzQyNjgtZDM2YWU0NzEtMmUzMS00MTMyLWEzNGItNzAxZmEzN2NlNDYwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA1NTYwM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTgwNGU3ZDNkZmQyZmUwYzg1NmMxNTYzMDgzNGRjNzY2ZTkzMjQ5YTc2NjIwMjUzMDdjNzNhZjM3ZWM3ZmIwN2QmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.cjZcqmcgEMY-LzNkvcH8Nw9_a1G9Y7uTSa8QSh_lyzI)
A simple fix would be to always return
None
whenasOpt
is called on theJsUndefined
object.We tested the performance of the function on version
3.0.4
witchScala 2.13.14
andJava 21
with 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: