When I look at the flamegraphs generated for scala3-benchmarks, I found AppliedUniques.linkedListLoop / WeakHashSet.linkedListLoop accounts for several % (4-5%) on some benchmarks.
linkedListLoop is traversing on the chain (of separate chaining), for looking up an entry from the chain.
One obvious optimization I realized is that, currently we always dereference WeakReference on the chain, and compare it with an entry we're looking up, but we should be able to compare hash and skip if they doesn't match.
|
@tailrec |
|
def linkedListLoop(entry: Entry[AppliedType] | Null): AppliedType = entry match |
|
case null => addEntryAt(bucket, newType, h, oldHead) |
|
case _ => |
|
val e = entry.get |
|
if e != null && (e.tycon eq tycon) && e.args.eqElements(args) then e |
|
else linkedListLoop(entry.tail) |
|
|
|
linkedListLoop(oldHead) |
|
end if |
When I look at the flamegraphs generated for
scala3-benchmarks, I foundAppliedUniques.linkedListLoop/WeakHashSet.linkedListLoopaccounts for several % (4-5%) on some benchmarks.linkedListLoopis traversing on the chain (of separate chaining), for looking up an entry from the chain.One obvious optimization I realized is that, currently we always dereference WeakReference on the chain, and compare it with an entry we're looking up, but we should be able to compare hash and skip if they doesn't match.
scala3/compiler/src/dotty/tools/dotc/core/Uniques.scala
Lines 92 to 101 in 96cca47