private static SimulatedBuildStats GetSimulatedBuildTime( int nodeCount, Func <NodeId, TimeSpan> getElapedTime, IDictionary <AbsolutePath, HashSet <NodeId> > pathToDownstreamPips, IDictionary <string, HashSet <NodeId> > packageToDownstreamPips, IDictionary <AbsolutePath, Tuple <TimeSpan, NodeId> > pathToCriticalPath, IDictionary <AbsolutePath, double> pathToImpactingFileTime, IDictionary <string, TimeSpan> packageToCriticalPath, IDictionary <string, double> packageToImpactingFileTime, List <AbsolutePath> files, IEnumerable <string> packages, SimulatedBuildParams buildParams) { double cacheHitRate; AbsolutePath highestImpactingCpuTimeFile; double maxCpuImpactingFileTime; string highestImpactingCpuTimePackage; double maxCpuImpactingPackageTime; double cpuMillis = GetSimulatedCpuMilliseconds(nodeCount, getElapedTime, pathToDownstreamPips, packageToDownstreamPips, pathToImpactingFileTime, packageToImpactingFileTime, files, packages, out cacheHitRate, out highestImpactingCpuTimeFile, out maxCpuImpactingFileTime, out highestImpactingCpuTimePackage, out maxCpuImpactingPackageTime); AbsolutePath highestImpactingCriticalPathFile; string highestImpactingCriticalPathPackage; bool packageWasHighestImpacting; TimeSpan criticalPathTime = GetSimulatedLongestCriticalPath(pathToCriticalPath, packageToCriticalPath, files, packages, out highestImpactingCriticalPathFile, out highestImpactingCriticalPathPackage, out packageWasHighestImpacting); double cpuMillisPerCore = cpuMillis / buildParams.NumberCores; double adjustedCpuMillis = cpuMillis * (1 + buildParams.PercentOverhead / 100); double adjustedCpuMillisPerCore = adjustedCpuMillis / buildParams.NumberCores; double adjustedCriticalPathMillis = criticalPathTime.TotalMilliseconds * (1 + buildParams.PercentCriticalPathOverhead / 100); double coresRequired = adjustedCpuMillis / adjustedCriticalPathMillis; string limitingFactor = adjustedCpuMillisPerCore > adjustedCriticalPathMillis ? "CPU Time" : "Critical Path"; AbsolutePath highestImpactingFile = adjustedCpuMillisPerCore > adjustedCriticalPathMillis ? highestImpactingCpuTimeFile : highestImpactingCriticalPathFile; double buildTime = Math.Max(adjustedCpuMillisPerCore, adjustedCriticalPathMillis) + buildParams.FixedOverheadMillis; return(new SimulatedBuildStats { CriticalPathMillis = criticalPathTime.TotalMilliseconds, CpuTimeMillis = cpuMillis, CpuTimePerCore = cpuMillisPerCore, BuildTimeMillis = buildTime, BuildParams = buildParams, LimitingFactor = limitingFactor, CoresRequired = coresRequired, CacheHitRate = cacheHitRate, HighestImpactingFile = highestImpactingFile, HighestImpactingCpuFile = highestImpactingCpuTimeFile, HighestImpactingCriticalPathFile = highestImpactingCriticalPathFile, HighestImpactingCpuFileTime = maxCpuImpactingFileTime, HighestImpactingCpuPackage = highestImpactingCpuTimePackage, HighestImpactingCpuPackageTime = maxCpuImpactingPackageTime, HighestImpactingCriticalPathPackage = highestImpactingCriticalPathPackage, PackageWasHighestImpactingCriticalPath = packageWasHighestImpacting }); }
public static List <SimulatedBuildStats> SimulateBuilds( int nodeCount, Func <NodeId, TimeSpan> getElapedTime, IDictionary <AbsolutePath, HashSet <NodeId> > pathToDownstreamPips, IDictionary <string, HashSet <NodeId> > packageToDownstreamPips, IDictionary <AbsolutePath, Tuple <TimeSpan, NodeId> > pathToCriticalPath, IDictionary <AbsolutePath, double> pathToCputTime, IDictionary <string, TimeSpan> packageToCriticalPath, IDictionary <string, double> packageToImpactingFileTime, List <Tuple <DateTime, long, List <AbsolutePath>, List <string> > > changeLists, int numberOfCores, double percentOverhead, double percentCriticalPathOverhead, double fixedOverheadMillis) { List <AbsolutePath> filesChangedInCurrentBuild = new List <AbsolutePath>(); HashSet <string> packagesChangedInCurrentBuild = new HashSet <string>(); DateTime nextReadyTime = changeLists.First().Item1; List <SimulatedBuildStats> buildTimes = new List <SimulatedBuildStats>(); int i = 0; int numberChangelists = 0; string clsInBuild = string.Empty; foreach (var changeList in changeLists) { clsInBuild += changeList.Item2 + "_"; numberChangelists++; filesChangedInCurrentBuild.AddRange(changeList.Item3); foreach (var package in changeList.Item4) { if (packageToDownstreamPips.ContainsKey(package) && packageToCriticalPath.ContainsKey(package) && packageToImpactingFileTime.ContainsKey(package)) { packagesChangedInCurrentBuild.Add(package); } } if (nextReadyTime <= changeList.Item1 && filesChangedInCurrentBuild.Any()) { SimulatedBuildParams buildParams = new SimulatedBuildParams() { FixedOverheadMillis = fixedOverheadMillis, PercentOverhead = percentOverhead, PercentCriticalPathOverhead = percentCriticalPathOverhead, NumberCores = numberOfCores, NumberOfChangeLists = numberChangelists, ChangeListsInBuild = clsInBuild, DateRun = nextReadyTime }; SimulatedBuildStats btstats = GetSimulatedBuildTime( nodeCount, getElapedTime, pathToDownstreamPips, packageToDownstreamPips, pathToCriticalPath, pathToCputTime, packageToCriticalPath, packageToImpactingFileTime, filesChangedInCurrentBuild, packagesChangedInCurrentBuild, buildParams); Console.WriteLine("Simulated: " + i + " of " + changeLists.Count + " changelists"); buildTimes.Add(btstats); numberChangelists = 0; nextReadyTime += TimeSpan.FromMilliseconds(btstats.BuildTimeMillis); filesChangedInCurrentBuild.Clear(); packagesChangedInCurrentBuild = new HashSet <string>(); clsInBuild = string.Empty; } i++; } if (filesChangedInCurrentBuild.Any()) { SimulatedBuildParams buildParams = new SimulatedBuildParams() { FixedOverheadMillis = fixedOverheadMillis, PercentOverhead = percentOverhead, PercentCriticalPathOverhead = percentCriticalPathOverhead, NumberCores = numberOfCores, NumberOfChangeLists = numberChangelists, ChangeListsInBuild = clsInBuild, DateRun = nextReadyTime }; SimulatedBuildStats btstats = GetSimulatedBuildTime( nodeCount, getElapedTime, pathToDownstreamPips, packageToDownstreamPips, pathToCriticalPath, pathToCputTime, packageToCriticalPath, packageToImpactingFileTime, filesChangedInCurrentBuild, packagesChangedInCurrentBuild, buildParams); buildTimes.Add(btstats); } return(buildTimes); }