Replace usages of java.util.HashMap with persistent map to optimize

memory allocation.
This commit is contained in:
Fedor Isakov 2019-05-17 16:26:56 +02:00
parent 3b638b2d08
commit c051542440
4 changed files with 29 additions and 30 deletions

View File

@ -16,6 +16,8 @@
package jetbrains.mps.logic.reactor.core
import com.github.andrewoma.dexx.collection.Maps
import com.github.andrewoma.dexx.collection.Map as PersMap
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
import jetbrains.mps.logic.reactor.logical.MetaLogical
import jetbrains.mps.logic.reactor.program.Constraint
@ -36,4 +38,7 @@ interface OccurrenceMatcher {
}
typealias Subst = Map<MetaLogical<*>, Any>
typealias Subst = PersMap<MetaLogical<*>, Any>
fun emptySubst() : Subst = Maps.of()

View File

@ -16,8 +16,10 @@
package jetbrains.mps.logic.reactor.core.internal
import com.github.andrewoma.dexx.collection.Maps
import jetbrains.mps.logic.reactor.core.OccurrenceMatcher
import jetbrains.mps.logic.reactor.core.Subst
import jetbrains.mps.logic.reactor.core.emptySubst
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalOwner
@ -28,13 +30,9 @@ import java.util.*
internal class OccurrenceMatcherImpl(val contextSubst: Subst? = null) : OccurrenceMatcher {
companion object {
private var matchSubst : Subst? = null
val EMPTY_SUBST : Subst = Collections.emptyMap()
}
private var matchSubst : MutableMap<MetaLogical<*>, Any>? = null
override fun substitution(): Subst = matchSubst ?: (contextSubst ?: EMPTY_SUBST)
override fun substitution(): Subst = matchSubst ?: (contextSubst ?: emptySubst())
/**
* Matches constraint and occurrence.
@ -68,13 +66,13 @@ internal class OccurrenceMatcherImpl(val contextSubst: Subst? = null) : Occurren
is MetaLogical<*> -> {
// recursion with existing substitution or new substitution
if (matchSubst == null) {
this.matchSubst = if (contextSubst != null) HashMap(contextSubst) else emptySubst()
this.matchSubst = if (contextSubst != null) contextSubst else emptySubst()
}
if (matchSubst!!.containsKey(ptn))
matchSubst!![ptn].let { matchAny(it, trg) }
else
matchSubst!!.put(ptn, trg!!).run { true }
matchSubst!!.put(ptn, trg!!).also { matchSubst = it }.run { true }
}
is Term ->
when {
@ -175,7 +173,5 @@ internal class OccurrenceMatcherImpl(val contextSubst: Subst? = null) : Occurren
}
fun emptySubst() = HashMap<MetaLogical<*>, Any>(4)
fun createOccurrenceMatcher(contextSubst: Subst? = null): OccurrenceMatcher =
OccurrenceMatcherImpl(contextSubst)

View File

@ -16,6 +16,7 @@
package jetbrains.mps.logic.reactor.core.internal
import com.github.andrewoma.dexx.collection.Maps
import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
import jetbrains.mps.logic.reactor.logical.MetaLogical
@ -92,7 +93,7 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher {
abstract fun combine(that: AlphaNode): ReteNode
open fun collectData(occArray: Array<Occurrence?>, allSubst: MutableMap<MetaLogical<*>, Any>) {}
open fun collectData(occArray: Array<Occurrence?>, allSubst: Subst): Subst = allSubst
}
@ -118,14 +119,14 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher {
val subst: Subst) : ReteNode()
{
val metaIndices: BitSet? =
if (subst.isNotEmpty()) bitSet(subst.keys.map { metaLogical -> indexOf(metaLogical) }) else null
if (!subst.isEmpty) bitSet(subst.keys().map { metaLogical -> indexOf(metaLogical) }) else null
val occIdx = indexOf(occurrence)
private val idx2subst = HashMap<Int, Any?>()
init {
for ((meta, subst) in subst.entries) {
for ((meta, subst) in subst.asMap().entries) {
idx2subst[indexOf(meta)] = subst
}
}
@ -145,11 +146,9 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher {
override fun combine(that: AlphaNode): ReteNode = BetaNode(this, that)
override fun collectData(occArray: Array<Occurrence?>, allSubst: MutableMap<MetaLogical<*>, Any>) {
override fun collectData(occArray: Array<Occurrence?>, allSubst: Subst): Subst {
occArray[posInHead] = occurrence
for ((k, v) in subst) {
allSubst.put(k, v)
}
return subst.fold(allSubst) { acc, (k, v) -> acc.put(k, v) }
}
}
@ -206,10 +205,8 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher {
override fun combine(that: AlphaNode): ReteNode = BetaNode(this, that)
override fun collectData(occArray: Array<Occurrence?>, allSubst: MutableMap<MetaLogical<*>, Any>) {
right.collectData(occArray, allSubst)
left.collectData(occArray, allSubst)
}
override fun collectData(occArray: Array<Occurrence?>, allSubst: Subst): Subst =
left.collectData(occArray, right.collectData(occArray, allSubst))
}
@ -295,7 +292,7 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher {
// any excluded occurrences?
if (n.containsOccurrence(skipOccIndices)) continue
val allSubst = HashMap<MetaLogical<*>, Any>()
val allSubst : Subst = emptySubst()
val occArray = arrayOfNulls<Occurrence>(headSize)
n.collectData(occArray, allSubst)

View File

@ -1,3 +1,4 @@
import com.github.andrewoma.dexx.collection.Maps
import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.core.internal.createOccurrenceMatcher
import jetbrains.mps.logic.reactor.core.internal.logical
@ -107,28 +108,28 @@ class TestRuleMatcher {
val foofx = MockConstraint(ConstraintSymbol("foo", 1), term("f", metaVar(X)))
// [X -> free] |- foo(f { X }) = foo(f { X })
createOccurrenceMatcher(arrayOf(X to logicalVar(xLogical)).toMap()).
createOccurrenceMatcher(Maps.of(X, logicalVar(xLogical))).
matches(foofx, occurrence("foo", term("f", logicalVar(xLogical)))) shouldBe true
// [X -> free] |- foo(f { X }) != foo(f { Y })
createOccurrenceMatcher(arrayOf(X to logicalVar(xLogical)).toMap()).
createOccurrenceMatcher(Maps.of(X, logicalVar(xLogical))).
matches(foofx, occurrence("foo", term("f", logicalVar(yLogical)))) shouldBe false
// [X -> free] |- foo(f { X }) != foo(f { h })
createOccurrenceMatcher(arrayOf(X to logicalVar(xLogical)).toMap()).
createOccurrenceMatcher(Maps.of(X, logicalVar(xLogical))).
matches(foofx, occurrence("foo", parseTerm("f { h }"))) shouldBe false
// [X -> free] |- foo(f { X }) != foo(f { Y = h })
yLogical.set(term("h"))
createOccurrenceMatcher(arrayOf(X to logicalVar(xLogical)).toMap()).
createOccurrenceMatcher(Maps.of(X, logicalVar(xLogical))).
matches(foofx, occurrence("foo", term("f", logicalVar(yLogical)))) shouldBe false
// [X -> h] |- foo(f { X }) = foo(f { h })
createOccurrenceMatcher(arrayOf(X to term("h")).toMap()).
createOccurrenceMatcher(Maps.of(X, term("h"))).
matches(foofx, occurrence("foo", parseTerm("f { h }"))) shouldBe true
// [X -> h] |- foo(f { X }) != foo(f { Z })
createOccurrenceMatcher(arrayOf(X to term("h")).toMap()).
createOccurrenceMatcher(Maps.of(X, term("h"))).
matches(foofx, occurrence("foo", term("f", logicalVar(zLogical)))) shouldBe false
// [X -> h] |- foo(f { X }) = foo(f { Z = h })
zLogical.set(term("h"))
createOccurrenceMatcher(arrayOf(X to term("h")).toMap()).
createOccurrenceMatcher(Maps.of(X, term("h"))).
matches(foofx, occurrence("foo", term("f", logicalVar(zLogical)))) shouldBe true
}