/// <summary> /// Reads the hierarchy from a plan file. /// </summary> private void ReadHierarchy(StreamReader file) { while (!file.EndOfStream) { string line = file.ReadLine(); if (line.Length == 0) { return; } string[] values = line.Split(new char[] { ' ' }); if (values.Length < 1) { throw new InvalidDataException("Too few values in hierarchy"); } int configId = Convert.ToInt32(values[0], CultureInfo.InvariantCulture); PlanConfigData parent = _configIdToData[configId]; for (int i = 1; i < values.Length; i++) { int childId = Convert.ToInt32(values[i], CultureInfo.InvariantCulture); PlanConfigData child = _configIdToData[childId]; parent.AddReference(child); } } }
/// <summary> /// Reads the accumulated time and path information for each configuration from the plan file. /// </summary> private void ReadTimes(StreamReader file) { while (!file.EndOfStream) { string line = file.ReadLine(); if (line.Length == 0) { return; } string[] values = line.Split(new char[] { ' ' }); if (values.Length < 3) { throw new InvalidDataException("Too few values in build plan."); } int configId = Convert.ToInt32(values[0], CultureInfo.InvariantCulture); double accumulatedTime = Convert.ToDouble(values[1], CultureInfo.InvariantCulture); string configFullPath = values[2]; PlanConfigData data = new PlanConfigData(configId, configFullPath, accumulatedTime); _configIdToData[configId] = data; _configPathToData[configFullPath] = data; MaximumConfigurationId = Math.Max(MaximumConfigurationId, configId); } }
/// <summary> /// This method finds all of the paths which lead to any given project /// </summary> private void DoRecursiveAnalysis() { Stack <PlanConfigData> currentPath = new Stack <PlanConfigData>(); PlanConfigData root = _configIdToData[1]; RecursiveVisitNodes(root, currentPath); }
/// <summary> /// Recursively visits all nodes in the hierarchy. /// </summary> private void RecursiveVisitNodes(PlanConfigData root, Stack <PlanConfigData> currentPath) { // Store the current path as a new path for this config List <Stack <PlanConfigData> > pathsForConfig; if (!_configIdToPaths.TryGetValue(root.ConfigId, out pathsForConfig)) { pathsForConfig = new List <Stack <PlanConfigData> >(); _configIdToPaths[root.ConfigId] = pathsForConfig; } // Reverse the stack so we get a path from the root to this node. Stack <PlanConfigData> pathToAdd = new Stack <PlanConfigData>(currentPath); // And add it to the list of paths. pathsForConfig.Add(pathToAdd); // Now add ourselves to the current path currentPath.Push(root); // Visit our children foreach (PlanConfigData child in root.References) { RecursiveVisitNodes(child, currentPath); } // Remove ourselves from the current path currentPath.Pop(); }
/// <summary> /// Returns the config id with the greatest value according to the comparer. /// </summary> private int GetConfigWithComparison(IEnumerable <int> realConfigsToSchedule, Comparison <PlanConfigData> comparer) { PlanConfigData bestConfig = null; int bestRealConfigId = BuildRequestConfiguration.InvalidConfigurationId; foreach (int realConfigId in realConfigsToSchedule) { PlanConfigData configToConsider; if (!_configPathToData.TryGetValue(_configCache[realConfigId].ProjectFullPath, out configToConsider)) { // By default we assume configs we don't know about aren't as important, and will only schedule them // if nothing else is suitable if (bestRealConfigId == BuildRequestConfiguration.InvalidConfigurationId) { bestRealConfigId = realConfigId; } continue; } if (bestConfig == null || (comparer(bestConfig, configToConsider) < 0)) { bestConfig = configToConsider; bestRealConfigId = realConfigId; } } return(bestRealConfigId); }
/// <summary> /// Adds the specified configuration as a reference. /// </summary> public void AddReference(PlanConfigData reference) { if (!_references.Contains(reference)) { _references.Add(reference); // My own accumulated reference time and that of all of my referrers increases as well if (!reference._referrers.Contains(this)) { reference._referrers.Add(this); } _accumulatedTimeOfReferences += reference.AccumulatedTime; RecursivelyApplyReferenceTimeToReferrers(reference.AccumulatedTime); } }
/// <summary> /// Writes out configuration in order of the greatest total plan time. /// </summary> private void DetermineConfigsWithGreatestPlanTime() { List <int> projectsInOrderOfTotalPlanTime = new List <int>(_configIdToData.Keys); projectsInOrderOfTotalPlanTime.Sort(delegate(int left, int right) { return(-Comparer <double> .Default.Compare(_configIdToData[left].TotalPlanTime, _configIdToData[right].TotalPlanTime)); }); foreach (int configId in projectsInOrderOfTotalPlanTime) { PlanConfigData config = _configIdToData[configId]; Console.WriteLine("{0}: {1} ({2} referrers) {3}", configId, config.TotalPlanTime, config.ReferrerCount, config.ConfigFullPath); foreach (PlanConfigData referrer in config.Referrers) { Console.WriteLine(" {0} {1}", referrer.ConfigId, referrer.ConfigFullPath); } Console.WriteLine(); } Console.WriteLine(); }
/// <summary> /// Recursively visits all nodes in the hierarchy. /// </summary> private void RecursiveVisitNodes(PlanConfigData root, Stack<PlanConfigData> currentPath) { // Store the current path as a new path for this config List<Stack<PlanConfigData>> pathsForConfig; if (!_configIdToPaths.TryGetValue(root.ConfigId, out pathsForConfig)) { pathsForConfig = new List<Stack<PlanConfigData>>(); _configIdToPaths[root.ConfigId] = pathsForConfig; } // Reverse the stack so we get a path from the root to this node. Stack<PlanConfigData> pathToAdd = new Stack<PlanConfigData>(currentPath); // And add it to the list of paths. pathsForConfig.Add(pathToAdd); // Now add ourselves to the current path currentPath.Push(root); // Visit our children foreach (PlanConfigData child in root.References) { RecursiveVisitNodes(child, currentPath); } // Remove ourselves from the current path currentPath.Pop(); }