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

Share instance of ClassTag in a ClassValue based cache #7879

Merged
merged 1 commit into from Jul 17, 2019

Conversation

retronym
Copy link
Member

A dynamic alternative to #7862

@lrytz
Copy link
Member

lrytz commented Mar 15, 2019

Also a simpler alternative :-) Looks good.

@retronym
Copy link
Member Author

retronym commented Mar 15, 2019

I'll take a look at the compiler performance (and profiles thereof) of the second commit to see if the cost of ClassValue hashmap lookup is perceptible or not.

@retronym
Copy link
Member Author

The profile recorded one sample (of 5966) with ClassValue.get on the stack. The recorded times were a tiny bit slower than the previous commit, but there is some fluctuation due to JIT variance in those numbers.

We could create a way to enable the old behaviour with a system property to be more conservative.

I should also do a direct microbenchmark to see how the worst case looks.

@retronym retronym added the WIP label Mar 20, 2019
@retronym retronym changed the base branch from 2.12.x to 2.13.x May 30, 2019 06:25
@retronym retronym marked this pull request as ready for review May 30, 2019 06:25
@retronym retronym removed the WIP label May 30, 2019
@retronym
Copy link
Member Author

retronym commented May 30, 2019

The new benchmark actually improves (slightly) with the ClassValue cache.

[info] Benchmark                         Mode  Cnt   Score   Error  Units
[info] ClassTagBenchmark.lookupClassTag  avgt   20  53.383 ± 0.638  ns/op // Baseline
[info] ClassTagBenchmark.lookupClassTag  avgt   20  37.261 ± 0.308  ns/op // Optimize ClassTag.apply
...
[info] ClassTagBenchmark.lookupClassTag  avgt   20  35.012 ± 0.216  ns/op // Share instance of ClassTag ...

@retronym
Copy link
Member Author

/synch

case _ => new GenericClassTag[T](runtimeClass1)
}
def apply[T](runtimeClass1: jClass[_]): ClassTag[T] = runtimeClass1 match {
case x if x.isPrimitive => primitiveClassTag(runtimeClass1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it better to have this logic in the computeValue
depends on the frequency of lookup etc

Ideally we could add the special values to the cache on its construction, but I can see a hook to allow that in ClassValue

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds more regular, I've added a commit.

It slightly improves the lookup speed of refererence classtags.

[info] ClassTagBenchmark.lookupClassTag  avgt   20  33.653 ± 0.644  ns/op

@retronym
Copy link
Member Author

I'm also applying this technique to TypeTag-s: #8112

@lrytz lrytz modified the milestones: 2.12.9, 2.13.1 Jul 16, 2019
@lrytz
Copy link
Member

lrytz commented Jul 16, 2019

That seems ready. @retronym, squash and merge?

@lrytz
Copy link
Member

lrytz commented Jul 16, 2019

And: it was originally against 2.12.x, then you moved it to 2.13, do you remember why?

@lrytz
Copy link
Member

lrytz commented Jul 16, 2019

Hmm, could this prevent classes from being garbage collected?

@lrytz
Copy link
Member

lrytz commented Jul 16, 2019

Ah, ClassValue uses weak references.

  - Optimize ClassTag.apply to avoid testing for primitive classes one-by-one.
  - Share instance of ClassTag in a ClassValue based cache and rely on
    this in the compiler where we had previously hoisted hot instances.
@retronym retronym changed the base branch from 2.13.x to 2.12.x July 16, 2019 21:49
@retronym
Copy link
Member Author

retronym commented Jul 16, 2019

Squashed and retargeted to 2.12.x

@retronym
Copy link
Member Author

/synch

@retronym
Copy link
Member Author

"validate-main — No corresponding job found on Jenkins. Failed to launch? Try /rebuild " looks like a bug in scabot when retargetting PRs from 2.13.x to 2.13.x.

@retronym retronym merged commit b5029ab into scala:2.12.x Jul 17, 2019
@retronym retronym modified the milestones: 2.13.1, 2.12.9 Jul 17, 2019
@SethTisue SethTisue added the performance the need for speed. usually compiler performance, sometimes runtime performance. label Jul 18, 2019
@lrytz lrytz mentioned this pull request Oct 26, 2020
@mkurz
Copy link
Contributor

mkurz commented Feb 1, 2021

@retronym @lrytz This never made it into 2.13.x even though in #8242 it says PICK.
Will you forward port this finally or isn't it worth it? If you do, you also should forward port #9276 and #9361 afterwards to fix a classloader leak this patch here introduced.

@retronym
Copy link
Member Author

retronym commented Feb 2, 2021

Thanks for the reminder. I'll forward port it this week with the subsequent patch to avoid the leak.

retronym added a commit to retronym/scala that referenced this pull request Feb 5, 2021
@retronym
Copy link
Member Author

retronym commented Feb 5, 2021

Forward port proposed in #9487

retronym added a commit to retronym/scala that referenced this pull request Feb 7, 2021
lrytz pushed a commit to retronym/scala that referenced this pull request Feb 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance the need for speed. usually compiler performance, sometimes runtime performance.
Projects
None yet
6 participants