From c051542440753d1caa43c91d7155fb06e1c3a24f Mon Sep 17 00:00:00 2001 From: Fedor Isakov Date: Fri, 17 May 2019 16:26:56 +0200 Subject: [PATCH] Replace usages of java.util.HashMap with persistent map to optimize memory allocation. --- .../logic/reactor/core/OccurrenceMatcher.kt | 7 ++++++- .../core/internal/OccurrenceMatcherImpl.kt | 16 ++++++-------- .../core/internal/ReteRuleMatcherImpl.kt | 21 ++++++++----------- reactor/Test/test/TestRuleMatcher.kt | 15 ++++++------- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceMatcher.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceMatcher.kt index dad4089d..3ec27c80 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceMatcher.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/OccurrenceMatcher.kt @@ -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, Any> +typealias Subst = PersMap, Any> + +fun emptySubst() : Subst = Maps.of() + diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/OccurrenceMatcherImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/OccurrenceMatcherImpl.kt index 25aa7898..01721f3d 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/OccurrenceMatcherImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/OccurrenceMatcherImpl.kt @@ -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, 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, Any>(4) - fun createOccurrenceMatcher(contextSubst: Subst? = null): OccurrenceMatcher = OccurrenceMatcherImpl(contextSubst) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt index 5f821682..ba31e3e4 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt @@ -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, allSubst: MutableMap, Any>) {} + open fun collectData(occArray: Array, 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() 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, allSubst: MutableMap, Any>) { + override fun collectData(occArray: Array, 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, allSubst: MutableMap, Any>) { - right.collectData(occArray, allSubst) - left.collectData(occArray, allSubst) - } + override fun collectData(occArray: Array, 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, Any>() + val allSubst : Subst = emptySubst() val occArray = arrayOfNulls(headSize) n.collectData(occArray, allSubst) diff --git a/reactor/Test/test/TestRuleMatcher.kt b/reactor/Test/test/TestRuleMatcher.kt index 5c15d384..d60810bc 100644 --- a/reactor/Test/test/TestRuleMatcher.kt +++ b/reactor/Test/test/TestRuleMatcher.kt @@ -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 }