10BC0 Replace (Par)TrieMap with ConcurrentHashMap in IncOptimizer by gzm0 · Pull Request #4974 · scala-js/scala-js · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Replace (Par)TrieMap with ConcurrentHashMap in IncOptimizer
- Reduces residual retained size of the IncOptimizer on the test suite
  from 166MB to 144MB.
- ~10% batch speedup on the optimizer.
  • Loading branch information
gzm0 committed Apr 6, 2024
commit d3c42e1370b8dd1b043061c3df2985a375691494
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,20 @@ package org.scalajs.linker.frontend.optimizer

import scala.annotation.tailrec

import scala.collection.concurrent.TrieMap
import scala.collection.parallel.mutable.{ParTrieMap, ParArray}
import scala.collection.parallel.mutable.ParArray
import scala.collection.parallel._

import java.util.concurrent.atomic._

private[optimizer] object ParCollOps extends AbsCollOps {
type Map[K, V] = TrieMap[K, V]
type ParMap[K, V] = ParTrieMap[K, V]
type AccMap[K, V] = TrieMap[K, Addable[V]]
type ParIterable[V] = ParArray[V]
type Addable[V] = AtomicReference[List[V]]

def emptyAccMap[K, V]: AccMap[K, V] = TrieMap.empty
def emptyMap[K, V]: Map[K, V] = TrieMap.empty
def emptyParMap[K, V]: ParMap[K, V] = ParTrieMap.empty
def parThreshold: Long = 1 // max parallelism

def emptyParIterable[V]: ParIterable[V] = ParArray.empty
def emptyAddable[V]: Addable[V] = new AtomicReference[List[V]](Nil)

// Operations on ParMap
def isEmpty[K, V](map: ParMap[K, V]): Boolean = map.isEmpty
def forceGet[K, V](map: ParMap[K, V], k: K): V = map(k)
def get[K, V](map: ParMap[K, V], k: K): Option[V] = map.get(k)
def put[K, V](map: ParMap[K, V], k: K, v: V): Unit = map.put(k, v)
def remove[K, V](map: ParMap[K, V], k: K): Option[V] = map.remove(k)

def retain[K, V](map: ParMap[K, V])(p: (K, V) => Boolean): Unit = {
map.foreach { case (k, v) =>
if (!p(k, v))
map.remove(k)
}
}

def valuesForeach[K, V, U](map: ParMap[K, V])(f: V => U): Unit =
map.values.foreach(f)

// Operations on AccMap
def acc[K, V](map: AccMap[K, V], k: K, v: V): Unit =
add(map.getOrElseUpdate(k, emptyAddable), v)

def getAcc[K, V](map: AccMap[K, V], k: K): ParIterable[V] =
map.get(k).fold(emptyParIterable[V])(finishAdd(_))

def parFlatMapKeys[A, B](map: AccMap[A, _])(f: A => Option[B]): ParIterable[B] =
map.keys.flatMap(f(_)).toParArray

// Operations on ParIterable
def prepAdd[V](it: ParIterable[V]): Addable[V] =
new AtomicReference(it.toList)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,15 @@ package org.scalajs.linker.frontend.optimizer

import language.higherKinds

import scala.collection.mutable

private[optimizer] trait AbsCollOps {
type Map[K, V] <: mutable.Map[K, V]
type ParMap[K, V] <: AnyRef
type AccMap[K, V] <: AnyRef
type ParIterable[V] <: AnyRef
type Addable[V] <: AnyRef

def emptyAccMap[K, V]: AccMap[K, V]
def emptyMap[K, V]: Map[K, V]
def emptyParMap[K, V]: ParMap[K, V]
def parThreshold: Long

def emptyParIterable[V]: ParIterable[V]
def emptyAddable[V]: Addable[V]

// Operations on ParMap
def isEmpty[K, V](map: ParMap[K, V]): Boolean
def forceGet[K, V](map: ParMap[K, V], k: K): V
def get[K, V](map: ParMap[K, V], k: K): Option[V]
def put[K, V](map: ParMap[K, V], k: K, v: V): Unit
def remove[K, V](map: ParMap[K, V], k: K): Option[V]
def retain[K, V](map: ParMap[K, V])(p: (K, V) => Boolean): Unit
def valuesForeach[K, V, U](map: ParMap[K, V])(f: V => U): Unit

// Operations on AccMap
def acc[K, V](map: AccMap[K, V], k: K, v: V): Unit
def getAcc[K, V](map: AccMap[K, V], k: K): ParIterable[V]
def parFlatMapKeys[A, B](map: AccMap[A, _])(f: A => Option[B]): ParIterable[B]

// Operations on ParIterable
def prepAdd[V](it: ParIterable[V]): Addable[V]
def add[V](addable: Addable[V], v: V): Unit
Expand Down
Loading
0