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

Use WeakHashSet instead of HashSet for hash-consing types #12935

Merged
merged 2 commits into from
Jul 6, 2021

Conversation

smarter
Copy link
Member

@smarter smarter commented Jun 25, 2021

This mimics what Scala 2 has been doing for a long time now and serves
the same purpose: it considerably reduces peak memory usage when
compiling some projects, for example previously compiling the Scalatest
tests required a heap of at least 11 GB, but now it fits in about 4 GB.

This required changing the implementation of WeakHashSet to subclass util.MutableSet
and to have overridable hash and isEqual methods just like HashSet, it also
required making various private methods protected since NamedTypeUniques
and AppliedUniques contain an inlined implementation of put.

This PR also changes the default load factor of a WeakHashSet from
0.75 to 0.5 to match the load factor we use for HashSets, though note that
Scala 2 has always been using 0.75.

For a history of the usage of WeakHashSet in Scala 2 see:

Thus making it a drop-in replacement for util.HashSet which will be
useful in the next commit where we'll use it in Uniques.

Also add `@constructorOnly` annotations for clarity.

Also remove all existing references to WeakHashSet in the code base
since it turns out they were all dead code.
This mimics what Scala 2 has been doing for a long time now and serves
the same purpose: it considerably reduces peak memory usage when
compiling some projects, for example previously compiling the Scalatest
tests required a heap of at least 11 GB, but now it fits in about 4 GB.

This required changing the implementation of WeakHashSet to have
overridable `hash` and `isEqual` methods just like HashSet, it also
required making various private methods protected since NamedTypeUniques
and AppliedUniques contain an inlined implementation of `put`.

This commit also changes the default load factor of a WeakHashSet from
0.75 to 0.5 to match the load factor we use for HashSets, though note that
Scala 2 has always been using 0.75.

For a history of the usage of WeakHashSet in Scala 2 see:
- scala/scala#247
- scala/scala#2605
- scala/scala#2901
@smarter
Copy link
Member Author

smarter commented Jun 25, 2021

test performance please

@dottybot
Copy link
Member

performance test scheduled: 1 job(s) in queue, 0 running.

@dottybot
Copy link
Member

Performance test finished successfully:

Visit https://dotty-bench.epfl.ch/12935/ to see the changes.

Benchmarks is based on merging with master (8163bff)

@odersky odersky merged commit 6011847 into scala:master Jul 6, 2021
@odersky odersky deleted the uniques-weakhashset-3 branch July 6, 2021 16:47
@xuwei-k
Copy link
Contributor

xuwei-k commented Jul 7, 2021

Thank you for improvements 🎉

Here is GC logs of my large project(600000 lines scala code)

Scala 3.0.1-RC2

pause 3.0.1-RC2
memory 3.0.1-RC2
graph 3.0.1-RC2

Scala 3.0.2-RC1-bin-20210706-6011847-NIGHTLY

pause 20210706-6011847-NIGHTLY
memory 20210706-6011847-NIGHTLY
graph 20210706-6011847-NIGHTLY

@smarter
Copy link
Member Author

smarter commented Jul 7, 2021

@xuwei-k Awesome, thank you for the report! Does your project also compile with Scala 2 and if so, do you get similar numbers there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants