Performance improvements for cli json report and minor refactoring (#724)

Major change:
* Identified hotspot in `JsonElem.hashCode` because it hashes children recursively. Hence simplified hashing scheme, reducing CPU time on `JsonReport.apply()` from 64.7 sec to 2.5 sec

Other minor changes:
* Make `JsonRequirement` use immutable classes
* Simplify `JsonRequirement` composition
This commit is contained in:
Yi Cheng 2018-01-01 11:55:43 -08:00 committed by GitHub
parent c8fa4638bc
commit 5da2210d7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 10 deletions

View File

@ -716,12 +716,12 @@ class Helper(
a.isOptional && notFound
}
val artifactToFile: collection.mutable.Map[String, File] = collection.mutable.Map()
val files0 = results.collect {
val artifactToFile = results.collect {
case (artifact: Artifact, \/-(f)) =>
artifactToFile.put(artifact.url, f)
f
}
(artifact.url, f)
}.toMap
val files0 = artifactToFile.values.toSeq
logger.foreach(_.stop())
@ -769,9 +769,9 @@ class Helper(
val artifacts: Seq[(Dependency, Artifact)] = res.dependencyArtifacts
val jsonReq = JsonPrintRequirement(artifactToFile, depToArtifacts, conflictResolutionForRoots)
val jsonReq = JsonPrintRequirement(artifactToFile, depToArtifacts)
val roots = deps.toVector.map(JsonElem(_, artifacts, Option(jsonReq), res, printExclusions = verbosityLevel >= 1, excluded = false, colors = false))
val jsonStr = JsonReport(roots, jsonReq.conflictResolutionForRoots)(_.children, _.reconciledVersionStr, _.requestedVersionStr, _.downloadedFiles)
val jsonStr = JsonReport(roots, conflictResolutionForRoots)(_.children, _.reconciledVersionStr, _.requestedVersionStr, _.downloadedFiles)
val pw = new PrintWriter(new File(jsonOutputFile))
pw.write(jsonStr)

View File

@ -1,6 +1,7 @@
package coursier.cli.util
import java.io.File
import java.util.Objects
import coursier.Artifact
import coursier.core.{Attributes, Dependency, Resolution}
@ -8,10 +9,10 @@ import coursier.util.Print
import scala.collection.mutable
import scala.collection.parallel.ParSeq
import argonaut._
import Argonaut._
import argonaut._, Argonaut._
final case class JsonPrintRequirement(fileByArtifact: collection.mutable.Map[String, File], depToArtifacts: Map[Dependency, Vector[Artifact]], conflictResolutionForRoots: Map[String, String])
final case class JsonPrintRequirement(fileByArtifact: Map[String, File], depToArtifacts: Map[Dependency, Vector[Artifact]])
final case class DepNode(coord: String, files: Vector[(String, String)], dependencies: Set[String])
@ -163,4 +164,11 @@ final case class JsonElem(dep: Dependency,
dependencies.map(JsonElem(_, artifacts, jsonPrintRequirement, resolution, colors, printExclusions, excluded = false)) ++
(if (printExclusions) excluded else Nil)
}
/**
* Override the hashcode to explicitly exclude `children`, because children will result in recursive hash on
* children's children, causing performance issue. Hash collision should be rare, but when that happens, the
* default equality check should take of the recursive aspect of `children`.
*/
override def hashCode(): Int = Objects.hash(dep, requestedVersionStr, reconciledVersion, downloadedFiles)
}