From acf5f06ded9471c812ecc1e9147dceaab0be4d30 Mon Sep 17 00:00:00 2001 From: Jason Feinstein Date: Tue, 25 May 2021 17:01:06 -0700 Subject: [PATCH] Memoize hashCode results to improve runtime performance when checking policies. PiperOrigin-RevId: 375826990 --- java/arcs/core/data/AccessPath.kt | 14 ++++++++++ java/arcs/core/data/Recipe.kt | 44 +++++++++++++++++++++++++++++++ java/arcs/core/data/Schema.kt | 23 ++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/java/arcs/core/data/AccessPath.kt b/java/arcs/core/data/AccessPath.kt index 31cd20714eb..eadb2b962b7 100644 --- a/java/arcs/core/data/AccessPath.kt +++ b/java/arcs/core/data/AccessPath.kt @@ -19,6 +19,8 @@ typealias StoreId = String * Examples of access paths are `input.app.packageName`, `store.rawText`, store.entites[i], etc. */ data class AccessPath(val root: Root, val selectors: List = emptyList()) { + private val hashCode by lazy { 31 * root.hashCode() + selectors.hashCode() } + /** * Constructs an [AccessPath] starting at a connection in [particle] identified * by [connectionSpec] followed by [selectors]. @@ -104,4 +106,16 @@ data class AccessPath(val root: Root, val selectors: List = emptyList( } return AccessPath(Root.HandleConnection(particle, root.connectionSpec), selectors) } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is AccessPath) return false + + if (root != other.root) return false + if (selectors != other.selectors) return false + + return true + } + + override fun hashCode(): Int = hashCode } diff --git a/java/arcs/core/data/Recipe.kt b/java/arcs/core/data/Recipe.kt index 97d52841915..9fff0ea5099 100644 --- a/java/arcs/core/data/Recipe.kt +++ b/java/arcs/core/data/Recipe.kt @@ -30,12 +30,26 @@ data class Recipe( val spec: ParticleSpec, val handleConnections: List ) { + private val hashCode by lazy { 31 * spec.hashCode() + handleConnections.hashCode() } + /** Representation of a handle connection in a particle. */ data class HandleConnection( val spec: HandleConnectionSpec, val handle: Handle, val type: Type ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Particle) return false + + if (spec != other.spec) return false + if (handleConnections != other.handleConnections) return false + + return true + } + + override fun hashCode(): Int = hashCode } /** Definition of a handle in a recipe. */ @@ -53,10 +67,40 @@ data class Recipe( CREATE, USE, MAP, COPY, JOIN } + private val hashCode by lazy { + var result = name.hashCode() + result = 31 * result + fate.hashCode() + result = 31 * result + type.hashCode() + result = 31 * result + (storageKey?.hashCode() ?: 0) + result = 31 * result + annotations.hashCode() + result = 31 * result + associatedHandles.hashCode() + result = 31 * result + id.hashCode() + result = 31 * result + tags.hashCode() + result + } + val capabilities: Capabilities get() { return Capabilities.fromAnnotations(annotations) } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Handle) return false + + if (name != other.name) return false + if (fate != other.fate) return false + if (type != other.type) return false + if (storageKey != other.storageKey) return false + if (annotations != other.annotations) return false + if (associatedHandles != other.associatedHandles) return false + if (id != other.id) return false + if (tags != other.tags) return false + + return true + } + + override fun hashCode(): Int = hashCode } } diff --git a/java/arcs/core/data/Schema.kt b/java/arcs/core/data/Schema.kt index 9f63af7c127..fa5130645ef 100644 --- a/java/arcs/core/data/Schema.kt +++ b/java/arcs/core/data/Schema.kt @@ -36,6 +36,14 @@ data class Schema( val refinementExpression: Expression = true.asExpr(), val queryExpression: Expression = true.asExpr() ) { + private val hashCode by lazy { + var result = names.hashCode() + result = 31 * result + fields.hashCode() + result = 31 * result + hash.hashCode() + result = 31 * result + refinementExpression.hashCode() + result = 31 * result + queryExpression.hashCode() + result + } /** Ensure instance is registered on construction. */ init { @@ -71,6 +79,21 @@ data class Schema( fun toString(options: Type.ToStringOptions) = names.map { it.name }.plusElement(fields.toString(options)).joinToString(" ") + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Schema) return false + + if (names != other.names) return false + if (fields != other.fields) return false + if (hash != other.hash) return false + if (refinementExpression != other.refinementExpression) return false + if (queryExpression != other.queryExpression) return false + + return true + } + + override fun hashCode(): Int = hashCode + data class Literal( val names: Set, val fields: SchemaFields,