Skip to content
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

Performance issue in TastyUtil::hasTastyFile when using Java classes #576

Closed
wix-andriusb opened this issue May 6, 2022 · 22 comments
Closed
Labels
2.14 3.x Something that likely has to be done in 3.x, not 2.x

Comments

@wix-andriusb
Copy link

wix-andriusb commented May 6, 2022

Hey, after I upgraded to a newer jackson version, I saw a lot of weird timeouts in our unit tests which should finish immediately.

After inspection I found this
tasty_trace

It seems like it checks if the class has a tasty file by operating on the the jar files which is a very costly operation if we assume that this is a cpu bound operation.

https://github.com/FasterXML/jackson-module-scala/blob/2.14/src/main/scala/com/fasterxml/jackson/module/scala/util/Classes.scala#L10-L12

It seems like this code path will always hit for classes defined in java(not scala classes), because the first two checks will always be false.

The tests succeeds if I add a retry, so I assume the result of this operation is cached?
Maybe it is possible to do val extendsScalaClass ?

@wix-andriusb
Copy link
Author

wix-andriusb commented May 6, 2022

Just to emphasise how much of a problem this is, from eyeballing this profile image it seems like a good 50% is spend in that method, I will try to hook into that method and collect some more accurate metrics
image

@pjfanning
Copy link
Member

pjfanning commented May 6, 2022

jackson caches the results of its class introspection so the performance hit should normally just happen the first time the class is used in jackson.

If you have to work with Java classes, why add the Scala module to the ObjectMapper? Or could you create a separate objectMapper for working with Java classes (one that doesn't add the Scala module)?

Could you elaborate on val extendsScalaClass? - I don't know what this means.

@wix-andriusb
Copy link
Author

wix-andriusb commented May 6, 2022

If you have to work with Java classes, why add the Scala module to the ObjectMapper? Or could you create a separate objectMapper for working with Java classes (one that doesn't add the Scala module)?

Hm might be a good idea, need to look into this for that particular case.

Could you elaborate on val extendsScalaClass? - I don't know what this means.

defining https://github.com/FasterXML/jackson-module-scala/blob/2.14/src/main/scala/com/fasterxml/jackson/module/scala/util/Classes.scala#L9 this as val extendsScalaClass so it gets evaluated immediately and only once, but if it is cached, I guess there is no difference

@wix-andriusb
Copy link
Author

It has to work with both, so I am out of luck.

@pjfanning
Copy link
Member

pjfanning commented May 6, 2022

It has to work with both, so I am out of luck.

It is unclear what you mean here.

  • the TastyUtil is important for supporting Scala 3 classes - so I'm not just going to remove this code
  • older versions of jackson-scala-module were unable to reliably spot when a class was a Java class or a Scala class - so there was undesirable behaviour with Java classes being treated as if they were Scala classes
  • v2 of jackson-scala-module is not very configurable - when v3 of jackson-scala-module comes out, there is better scope for making it configurable - in that release, I can add an option where user's can disable Scala 3 support - this will only be done when jackson v3 comes out and this does not appear to be happening in near future
  • ObjectMapper handling Java classes has an unnecessary overhead if you add the Scala module - I would recommend against using ObjectMappers with ScalaModule when you know a class is not a Scala class
  • I don't see why you can't increase the timeouts on your tests

@pjfanning pjfanning changed the title TastyUtil::hastTastyFile calls TastyUtil::hasTastyFile calls May 6, 2022
@pjfanning
Copy link
Member

also might be worth looking at https://github.com/pjfanning/jackson-caffeine-cache - you may not need the jar but read the README to see how you can increase the built-in cache

@wix-andriusb
Copy link
Author

wix-andriusb commented May 9, 2022

It is unclear what you mean here.

That particular object mapper is used for both, scala and java classes. Splitting is an option, but it is not a codebase I am familiar with. I am basically investigating what approach is the most feasible here to apply.

the TastyUtil is important for supporting Scala 3 classes - so I'm not just going to remove this code

I am trying to figure out what approach I should use so I am throwing out my issue into the open. I am not suggesting to remove it.

v2 of jackson-scala-module is not very configurable - when v3 of jackson-scala-module comes out, there is better scope for making it configurable - in that release, I can add an option where user's can disable Scala 3 support - this will only be done when jackson v3 comes out and this does not appear to be happening in near future

I wish it would be possible to do minor release with configuration additions.

I don't see why you can't increase the timeouts on your tests

There are 70 tests are breaking, I am just investigating a solution that might fix them all with one change. I have an option to increase the timeout for all of them, but something is still off, the futures themselves in the test finishes in time, I can't put my finger yet on the culprit which makes the test fail

@wix-andriusb
Copy link
Author

A config option would be nice to disable expensive reflection for non scala3, but I have a hunch that the test framework (specs2) I am using is doing something fishy.

@pjfanning pjfanning reopened this May 9, 2022
@pjfanning pjfanning added the 3.x Something that likely has to be done in 3.x, not 2.x label May 9, 2022
@jarekczek
Copy link

We have the same problem. It's hard for us to exclude scala module, as the configuration is set up globally. For the moment our only hope is jackson downgrade.

Cache seems not an option, as the performance problems come from extendsScalaClass() which is called before the cache is accessed. Here is the stacktrace from problematic code path:

at java.lang.Class.getResource(Class.java:2740)
at com.fasterxml.jackson.module.scala.util.TastyUtil$.hasTastyFile(TastyUtil.scala:22)
at com.fasterxml.jackson.module.scala.util.ClassW.extendsScalaClass(Classes.scala:12)
at com.fasterxml.jackson.module.scala.util.ClassW.extendsScalaClass$(Classes.scala:9)
at com.fasterxml.jackson.module.scala.util.ClassW$$anon$1.extendsScalaClass(Classes.scala:34)
at com.fasterxml.jackson.module.scala.introspect.ScalaAnnotationIntrospector$._descriptorFor(ScalaAnnotationIntrospectorModule.scala:229)

What we would like best is possibility to disable tasty files feature.

@pjfanning
Copy link
Member

for now, forking the code and producing your own copy with features added or removed is the most timely solution

@pjfanning
Copy link
Member

To be clear, neither of you have provided reproducible test cases and I remain sceptical that removing the Tasty file check or even making it configurable is the right answer.

The lookup results are essentially cached after the first use of the class but if you are seeing serious issues, then I think it is more likely the cached results are being cleared and the solution to that is described in https://github.com/pjfanning/jackson-caffeine-cache

@pjfanning
Copy link
Member

pjfanning commented May 17, 2022

I have added some code to the master branch - for the 3.0 release (that could be some way off)

@jarekczek
Copy link

jarekczek commented May 17, 2022

I still have no proof, however after editing ClassW and rebuilding the module - the performance issue is gone.

def extendsScalaClass: Boolean = {
  ClassW.productClass.isAssignableFrom(value) ||
  isScalaObject
  // || TastyUtil.hasTastyFile(value)
}

@pjfanning
Copy link
Member

pjfanning commented May 17, 2022

I did some testing and for non-Scala classes, there is no caching of the introspection results - meaning the work is duplicated on subsequent calls - I have added #578 and it will be released when v2.14.0 is released

@wix-andriusb
Copy link
Author

When will 2.14.0 be released?

@pjfanning
Copy link
Member

We release when rest of jackson ecosystem releases - to keep release nums consistent.

I get an issue like #581 and act on it.

If you are looking to upgrade jackson due to worries about CVEs, then the 2.12.7 release might be of interest. The TastyUtil is not in not in v2.12.

@wix-andriusb
Copy link
Author

I need 2.13 because of #514 I guess ill try to somehow look if our builds pass and then just wait it out

@pjfanning
Copy link
Member

2.14.0-rc1 is out

@wix-andriusb
Copy link
Author

Can you link to the release? I can't find it in the mvnrepository

@cowtowncoder
Copy link
Member

Mvnrepository takes days to update, so going forward please just look at place @pjfanning linked. That's where release goes relatively quickly.

@wix-andriusb
Copy link
Author

Thanks for clarifying, you guys are fast :)

@pjfanning pjfanning changed the title TastyUtil::hasTastyFile calls Performance issue in TastyUtil::hasTastyFile when using Java classes Oct 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.14 3.x Something that likely has to be done in 3.x, not 2.x
Projects
None yet
Development

No branches or pull requests

4 participants