Merge pull request #2034 from sbt/fix/2014

Cached resolution: Clean up old dynamic minigraphs. Fixes #2014
This commit is contained in:
Dale Wijnand
2015-05-24 00:48:46 +01:00
2 changed files with 32 additions and 6 deletions
@@ -4,6 +4,7 @@ package ivyint
import java.util.Date import java.util.Date
import java.net.URL import java.net.URL
import java.io.File import java.io.File
import java.text.SimpleDateFormat
import collection.concurrent import collection.concurrent
import collection.mutable import collection.mutable
import collection.immutable.ListMap import collection.immutable.ListMap
@@ -20,12 +21,19 @@ import org.apache.ivy.plugins.latest.{ ArtifactInfo => IvyArtifactInfo }
import org.apache.ivy.plugins.matcher.{ MapMatcher, PatternMatcher } import org.apache.ivy.plugins.matcher.{ MapMatcher, PatternMatcher }
import Configurations.{ System => _, _ } import Configurations.{ System => _, _ }
import annotation.tailrec import annotation.tailrec
import scala.concurrent.duration._
private[sbt] object CachedResolutionResolveCache { private[sbt] object CachedResolutionResolveCache {
def createID(organization: String, name: String, revision: String) = def createID(organization: String, name: String, revision: String) =
ModuleRevisionId.newInstance(organization, name, revision) ModuleRevisionId.newInstance(organization, name, revision)
def sbtOrgTemp = "org.scala-sbt.temp" def sbtOrgTemp = "org.scala-sbt.temp"
def graphVersion = "0.13.9" def graphVersion = "0.13.9"
val buildStartup: Long = System.currentTimeMillis
lazy val todayStr: String = toYyyymmdd(buildStartup)
lazy val tomorrowStr: String = toYyyymmdd(buildStartup + (1 day).toMillis)
lazy val yesterdayStr: String = toYyyymmdd(buildStartup - (1 day).toMillis)
def toYyyymmdd(timeSinceEpoch: Long): String = yyyymmdd.format(new Date(timeSinceEpoch))
lazy val yyyymmdd: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
} }
private[sbt] class CachedResolutionResolveCache() { private[sbt] class CachedResolutionResolveCache() {
@@ -137,7 +145,17 @@ private[sbt] class CachedResolutionResolveCache() {
val staticGraphDirectory = miniGraphPath / "static" val staticGraphDirectory = miniGraphPath / "static"
val dynamicGraphDirectory = miniGraphPath / "dynamic" val dynamicGraphDirectory = miniGraphPath / "dynamic"
val staticGraphPath = staticGraphDirectory / pathOrg / pathName / pathRevision / "graphs" / "graph.json" val staticGraphPath = staticGraphDirectory / pathOrg / pathName / pathRevision / "graphs" / "graph.json"
val dynamicGraphPath = dynamicGraphDirectory / logicalClock.toString / pathOrg / pathName / pathRevision / "graphs" / "graph.json" val dynamicGraphPath = dynamicGraphDirectory / todayStr / logicalClock.toString / pathOrg / pathName / pathRevision / "graphs" / "graph.json"
def cleanDynamicGraph(): Unit =
{
val list = IO.listFiles(dynamicGraphDirectory, DirectoryFilter).toList
list filterNot { d =>
(d.getName == todayStr) || (d.getName == tomorrowStr) || (d.getName == yesterdayStr)
} foreach { d =>
log.debug(s"deleting old graphs $d...")
IO.delete(d)
}
}
def loadMiniGraphFromFile: Option[Either[ResolveException, UpdateReport]] = def loadMiniGraphFromFile: Option[Either[ResolveException, UpdateReport]] =
(if (staticGraphPath.exists) Some(staticGraphPath) (if (staticGraphPath.exists) Some(staticGraphPath)
else if (dynamicGraphPath.exists) Some(dynamicGraphPath) else if (dynamicGraphPath.exists) Some(dynamicGraphPath)
@@ -175,6 +193,9 @@ private[sbt] class CachedResolutionResolveCache() {
val gp = if (changing) dynamicGraphPath val gp = if (changing) dynamicGraphPath
else staticGraphPath else staticGraphPath
log.debug(s"saving minigraph to $gp") log.debug(s"saving minigraph to $gp")
if (changing) {
cleanDynamicGraph()
}
JsonUtil.writeUpdateReport(ur, gp) JsonUtil.writeUpdateReport(ur, gp)
// limit the update cache size // limit the update cache size
if (updateReportCache.size > maxUpdateReportCacheSize) { if (updateReportCache.size > maxUpdateReportCacheSize) {
+10 -5
View File
@@ -4,6 +4,7 @@
[@jsuereth]: https://github.com/jsuereth [@jsuereth]: https://github.com/jsuereth
[1721]: https://github.com/sbt/sbt/issues/1721 [1721]: https://github.com/sbt/sbt/issues/1721
[2014]: https://github.com/sbt/sbt/issues/2014
[2030]: https://github.com/sbt/sbt/pull/2030 [2030]: https://github.com/sbt/sbt/pull/2030
### Fixes with compatibility implications ### Fixes with compatibility implications
@@ -12,15 +13,19 @@
### Bug fixes ### Bug fixes
- Fixes memory/performance issue with cached resolution. See below. - Fixes memory/performance issue with cached resolution. See below.
### Cached resolution fixes ### Cached resolution fixes
On a larger dependency graph, the JSON file growing to be 100MB+ On a larger dependency graph, the JSON file growing to be 100MB+
with 97% of taken up by *caller* information. with 97% of taken up by *caller* information.
The caller information is not useful once the graph is successfully resolved. The caller information is not useful once the graph is successfully resolved.
sbt 0.13.9 creates a single caller to represent all callers, To make the matter worse, these large JSON files were never cleaned up.
which fixes `OutOfMemoryException` seen on some builds,
and generally it should make JSON IO faster.
[#2030][2030]/[#1721][1721] by [@eed3si9n][@eed3si9n] sbt 0.13.9 creates a single caller to represent all callers,
which fixes `OutOfMemoryException` seen on some builds.
This generally shrinks the size of JSON, so it should make the IO operations faster.
Dynamic graphs will be rotated with directories named after `yyyy-mm-dd`,
and stale JSON files will be cleaned up after few days.
[#2030][2030]/[#1721][1721]/[#2014][2014] by [@eed3si9n][@eed3si9n]