Skip to content

Commit

Permalink
Merge pull request #672 from aml-org/W-15207889/performance-fixes
Browse files Browse the repository at this point in the history
W-15207889. Some performance improvements.
  • Loading branch information
jisoldi authored Mar 14, 2024
2 parents 95127a0 + be45ab4 commit f32b43e
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 16 deletions.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v16.17.1
5 changes: 5 additions & 0 deletions .sdkmanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=17.0.10-tem
scala=2.12.15
sbt=1.7.3
39 changes: 32 additions & 7 deletions shared/src/main/scala/amf/core/internal/remote/Cache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,40 @@ class Cache {
dependencyGraph.update(to, fromNodes.+(from))
}

protected def findCycles(node: String, acc: Set[String] = Set()): Boolean = {
if (acc.contains(node)) {
true
} else {
val sources = dependencyGraph.getOrElse(node, Set())
sources.exists { source =>
findCycles(source, acc + node)
protected def findCycles(initialNode: String): Boolean = {
// Mutable collections are used to improve performance
val allVisited = mutable.Set[String]()
val visitedStack = mutable.Stack[String]()

def innerFindCycles(currentNode: String): Boolean = {
if (visitedStack.contains(currentNode)) {
// There is a cycle
return true
}

if (allVisited.contains(currentNode)) {
// This node has already been visited
return false
}

allVisited.add(currentNode)
visitedStack.push(currentNode)

val newNodes = dependencyGraph.getOrElse(currentNode, Set())
for (newNode <- newNodes) {
if (findCycles(newNode)) {
// Cycle found
visitedStack.pop()
return true
}
}

// So far no cycles
visitedStack.pop()
false
}

innerFindCycles(initialNode)
}

protected def beforeLast(elms: List[String]): Option[String] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package amf.core.internal.transform.stages
import amf.core.client.scala.AMFGraphConfiguration
import amf.core.client.scala.errorhandling.AMFErrorHandler
import amf.core.internal.metamodel.Type.{ArrayLike, Iri}
import amf.core.internal.metamodel.domain.LinkableElementModel
import amf.core.client.scala.model.document.BaseUnit
import amf.core.client.scala.model.domain._
import amf.core.client.scala.transform.TransformationStep
import amf.core.internal.parser.domain.FieldEntry
import amf.core.client.scala.vocabulary.Namespace
import amf.core.internal.metamodel.Type.{ArrayLike, Iri}
import amf.core.internal.metamodel.domain.LinkableElementModel
import amf.core.internal.parser.domain.{Annotations, FieldEntry, Value}

import scala.collection.mutable
Expand All @@ -19,17 +18,23 @@ class UrlShortenerStage() extends TransformationStep {
errorHandler: AMFErrorHandler,
configuration: AMFGraphConfiguration
): BaseUnit = {
val ids: Set[String] = Set(model.id) ++ obtainNestedReferenceIds(model)
val ids: mutable.Set[String] = mutable.Set()
collectNestedReferenceIdsInSet(model, ids)
ids.add(model.id)

shorten(model, ids)
model.withId(base)
}

private def obtainNestedReferenceIds[T <: BaseUnit](model: T): Seq[String] = {
val ids = model.references.map(_.id)
ids ++ model.references.flatMap(obtainNestedReferenceIds)
private def collectNestedReferenceIdsInSet[T <: BaseUnit](model: T, set: mutable.Set[String]): Unit = {
if (!set.contains(model.id)) {
set += model.id

model.references.foreach(collectNestedReferenceIdsInSet(_, set))
}
}

def shorten(element: AmfElement, ids: Set[String]): Unit = {
def shorten(element: AmfElement, ids: Traversable[String]): Unit = {
element match {
case o: AmfObject =>
val shorthenId = shortener.shorten(o.id)
Expand Down Expand Up @@ -64,7 +69,7 @@ class UrlShortenerStage() extends TransformationStep {
shorten(element.annotations)
}

private def shortenIriValue(element: AmfElement, ids: Set[String]): AmfElement = {
private def shortenIriValue(element: AmfElement, ids: Traversable[String]): AmfElement = {
val stringValue = element.toString
if (ids.exists(i => stringValue.startsWith(i)))
AmfScalar(shortener.shorten(stringValue), element.annotations)
Expand Down

0 comments on commit f32b43e

Please sign in to comment.