You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use WeakHashSet instead of HashSet for hash-consing types
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
deflinkedListLoop(entry: Entry[A]):A= entry match {
186
-
casenull=>add()
171
+
casenull=>addEntryAt(bucket, elem, h, oldHead)
187
172
case _ =>
188
173
valentryElem= entry.get
189
-
if (elem.equals(entryElem)) entryElem
174
+
if (isEqual(elem, entryElem)) entryElem
190
175
else linkedListLoop(entry.tail)
191
176
}
192
177
@@ -200,14 +185,14 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
200
185
case _ =>
201
186
Stats.record(statsItem("-="))
202
187
removeStaleEntries()
203
-
valbucket=bucketFor(elem.hashCode)
188
+
valbucket=index(hash(elem))
204
189
205
190
206
191
207
192
@tailrec
208
193
deflinkedListLoop(prevEntry: Entry[A], entry: Entry[A]):Unit= entry match {
209
194
casenull=> ()
210
-
case _ ifelem.equals(entry.get) => remove(bucket, prevEntry, entry)
195
+
case _ ifisEqual(elem, entry.get) => remove(bucket, prevEntry, entry)
211
196
case _ => linkedListLoop(entry, entry.tail)
212
197
}
213
198
@@ -307,9 +292,9 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
307
292
assert(entry.get !=null, s"$entry had a null value indicated that gc activity was happening during diagnostic validation or that a null value was inserted")
308
293
computedCount +=1
309
294
valcachedHash= entry.hash
310
-
valrealHash= entry.get.hashCode
295
+
valrealHash=hash(entry.get)
311
296
assert(cachedHash == realHash, s"for $entry cached hash was $cachedHash but should have been $realHash")
312
-
valcomputedBucket=bucketFor(realHash)
297
+
valcomputedBucket=index(realHash)
313
298
assert(computedBucket == bucket, s"for $entry the computed bucket was $computedBucket but should have been $bucket")
314
299
315
300
entry = entry.tail
@@ -355,11 +340,6 @@ object WeakHashSet {
355
340
* A single entry in a WeakHashSet. It's a WeakReference plus a cached hash code and
356
341
* a link to the next Entry in the same bucket
357
342
*/
358
-
privateclassEntry[A](@constructorOnly element: A, valhash:Int, vartail:Entry[A], @constructorOnly queue: ReferenceQueue[A]) extendsWeakReference[A](element, queue)
359
-
360
-
privatefinalvaldefaultInitialCapacity=16
361
-
privatefinalvaldefaultLoadFactor=.75
343
+
classEntry[A](@constructorOnly element: A, valhash:Int, vartail:Entry[A], @constructorOnly queue: ReferenceQueue[A]) extendsWeakReference[A](element, queue)
0 commit comments