private void SimulateActual(PipExecutionData data, int actualConcurrency, MultiWriter writers) { // simulate with actual concurrency Console.WriteLine("Simulating actual build"); SimulationResult actualSimulation = new SimulationResult(data, data.AggregateCosts); actualSimulation.Simulate(actualConcurrency); Console.WriteLine("Done"); Console.WriteLine(); WriteActualAndSimulationResults(data, actualSimulation); writers.WriteLine("Edge Count: {0}", data.DirectedGraph.EdgeCount); writers.WriteLine("Pip Type Counts:"); foreach (var pipType in EnumTraits <PipType> .EnumerateValues()) { writers.WriteLine("{0}: {1}", data.PipTypeCounts[(int)pipType].ToString().PadLeft(10), pipType); } writers.WriteLine("Processes with timing information:{0} ", data.DirectedGraph.Nodes.Where(node => data.GetPipType(node) == PipType.Process && data.StartTimes[node] != 0).Count()); writers.WriteLine("Actual Total Build Time: {0} min", data.TotalDuration.ToMinutes()); writers.WriteLine("Actual Concurrency: {0}", data.ActualConcurrency); writers.WriteLine("Simulated total build time (using actual concurrency): {0} min", actualSimulation.TotalTime.ToMinutes()); // write down info for each critical path ulong criticalPathCost = WriteCriticalPathToResult(writers, data, actualSimulation); }
private static ulong WriteCriticalPathToResult(MultiWriter writers, PipExecutionData data, SimulationResult testSimulation) { int nameWidth; int count = 0; ulong criticalPathCost = 0; foreach (var p in data.GetSortedPips(2, true, n => data.GetPipType(n) == PipType.Process, n => data.AggregateCosts[n])) { // this is the actual critical path. This is not associated with the simulation as it only correlates to the dgg List <NodeId> criticalPath = new List <NodeId>(); NodeId criticalChainNode = p.Node; while (criticalChainNode.IsValid) { criticalPath.Add(criticalChainNode); criticalChainNode = data.CriticalChain[criticalChainNode]; } p.Priority.Max(ref criticalPathCost); writers.WriteLine("Critical Path {0}:", count++); writers.WriteLine("Critical Path Cost: {0} min", p.Priority.ToMinutes()); writers.WriteLine("Critical Path Length: {0}", criticalPath.Count); nameWidth = criticalPath.Select(n => data.GetName(n).Length).Max(); writers.WriteLine("Critical Path:\n {0}", string.Join(Environment.NewLine + " -> ", criticalPath // .Where(n => data.Durations[n] > 0) .Select(n => string.Format( "{0} ({1} min) [{2}] <{3}> [{4},{5}]", // .Select(n => string.Format("{0} ({1} min) [{2}] <{3}>", data.GetName(n).PadLeft(nameWidth), data.Durations[n].ToMinutes(), data.PipIds[n], data.GetPipType(n), testSimulation.StartTimes[n].ToMinutes(), testSimulation.EndTimes[n].ToMinutes())))); // data.PipTypes[n])))); } return(criticalPathCost); }
public override int Analyze() { Console.WriteLine("Analyzing"); var data = m_executionData; data.Compute(); Directory.CreateDirectory(resultsFormat.FormatWith(string.Empty)); int simulationCount = 24; int increment = 100; using (StreamWriter sw = new StreamWriter(resultsFormat.FormatWith("result.txt"))) { int actualConcurrency = data.ActualConcurrency <= 0 ? increment : data.ActualConcurrency; // write result.txt var writers = new MultiWriter(sw, Console.Out); //SimulateActual(data, actualConcurrency, writers); // a Pip is a process (entity of invocation) or a target for CB int nameWidth = data.LongestRunningPips.Select(n => data.GetName(n.Node).Length).Max(); writers.WriteLine(); writers.WriteLine("Top 20 Long Running Pips:"); foreach (var p in data.LongestRunningPips) { writers.WriteLine("{0} [{2}]: {1} min", data.GetName(p.Node).PadLeft(nameWidth), p.Priority.ToMinutes(), data.PipIds[p.Node]); } writers.WriteLine(); writers.WriteLine("Bottom 20 Shortest Running Processes:"); foreach (var p in data.ShortestRunningProcesses) { writers.WriteLine("{0} [{2}]: {1} min", data.GetName(p.Node).PadLeft(nameWidth), p.Priority.ToMinutes(), data.PipIds[p.Node]); } SimulationResult[] results = SimulateBuildWithVaryingThreatCount(data, simulationCount, increment); results = results.OrderBy(s => s.Threads.Count).ToArray(); string format = "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}"; writers.WriteLine(); writers.WriteLine("Results"); writers.WriteLine( format, "Thread Count", // 0 "Total Execution Time (min)", // 1 "Critical Path Length", // 2 "Critical Path Tail Pip", // 3 "Critical Path Idle Time (min)", // 4 "Total Active time (min)", // in minutes //5 "Total time (min)", // TotalTime 6 "Average Utilization", // 7 "Max Path Length", // 8 "Executed Pips") // 9 ; // the thread that took the most time excuting // cp in this case is not the actual critical path, but the thread that took the longest or the last to complete // even if the cp is 20 minutes, the cp as a thread in this context could be 30 due to limited ressources (machines/cores) // in terms of time the thread cp will be the same time as the actual cp // this information is per build for (int i = 0; i < results.Length; i++) { var result = results[i]; writers.WriteLine( format, result.Threads.Count, // Thread Count: number of cores that have been used result.TotalTime.ToMinutes(), // Total Execution Time (min): minutes that it took for the build result.ThreadWithLatestEndTime.Executions.Count, // Critical Path Length: result.ThreadWithLatestEndTime.Executions.Last().Id.Value, // Critical Path Tail Pip: result.ThreadWithLatestEndTime.IdleTime.ToMinutes(), // Critical Path Idle Time (min) result.TotalActiveTime.ToMinutes(), // totalactivetime in minutes result.TotalTime.ToMinutes(), // result.TotalTime Math.Round((double)result.TotalActiveTime / (double)((ulong)result.Threads.Count * result.TotalTime), 3), // Average Utilization result.Threads.Select(t => t.Executions.Count).Max(), result.Threads.Select(t => t.Executions.Count).Sum()); } // Console.ReadKey(); } return(0); }