Beispiel #1
0
        public void ComputeAggregateCosts()
        {
            PipAndPriority maxPipAndPriority = default(PipAndPriority);
            List <NodeId>  sortedNodes       = new List <NodeId>();

            sortedNodes.AddRange(DataflowGraph.Nodes);
            sortedNodes.Sort((n1, n2) => - DataflowGraph.GetNodeHeight(n1).CompareTo(DataflowGraph.GetNodeHeight(n2)));
            foreach (var node in sortedNodes)
            {
                //int maxConeConcurrency = 0;
                ulong  aggregateCost = 0, constrainedAggregateCost = 0;
                NodeId maxChild = NodeId.Invalid;
                foreach (var outgoing in DataflowGraph.GetOutgoingEdges(node))
                {
                    ConstrainedAggregateCosts[outgoing.OtherNode].Max(ref constrainedAggregateCost);

                    if (AggregateCosts[outgoing.OtherNode].Max(ref aggregateCost) || !maxChild.IsValid())
                    {
                        maxChild = outgoing.OtherNode;
                    }
                }

                aggregateCost       += Durations[node];
                AggregateCosts[node] = aggregateCost;
                aggregateCost.Max(ref MaxAggregateCost);
                CriticalChain[node] = maxChild;

                new PipAndPriority()
                {
                    Node     = node,
                    Priority = aggregateCost
                }.Max(ref maxPipAndPriority);
            }

            CriticalPathHeadNode = maxPipAndPriority.Node;

            NodeId criticalChainNode = CriticalPathHeadNode;

            while (criticalChainNode.IsValid())
            {
                CriticalPath.Add(criticalChainNode);
                criticalChainNode = CriticalChain[criticalChainNode];
            }
        }
Beispiel #2
0
        static void Main(string[] args)
        {
            PipExecutionData data = new PipExecutionData();

            if (args.Length != 1)
            {
                throw new ArgumentException("Specify directory path as only argument on command line");
            }

            string directory = args[0];
            string graphPath = Path.Combine(args[0], "graph.json");

            if (!File.Exists(graphPath))
            {
                throw new ArgumentException(string.Format("Graph does not exist at location: {0}", graphPath));
            }


            string resultsFormat = string.Format(@"{0}\sim\{{0}}", directory);

            Console.WriteLine("Loading graph...");

            Directory.CreateDirectory(string.Format(resultsFormat, ""));
            data.ReadAndCacheJsonGraph(Path.Combine(directory, "graph.json"));

            Console.WriteLine("Done");
            Console.WriteLine();

            Console.WriteLine("Saving runtime time table:");

            PipRuntimeTimeTable runtimeTable = new PipRuntimeTimeTable();

            foreach (var node in data.DataflowGraph.Nodes)
            {
                if (data.PipTypes[node] == PipType.Process)
                {
                    var  stableId     = (long)data.SemiStableHashes[node];
                    var  duration     = TimeSpan.FromTicks((long)data.Durations[node]);
                    uint milliseconds = (uint)Math.Min(duration.TotalMilliseconds, uint.MaxValue);
                    runtimeTable[stableId] = new PipHistoricPerfData(PipHistoricPerfData.DefaultTimeToLive, milliseconds);
                }
            }

            runtimeTable.SaveAsync(Path.Combine(directory, "RunningTimeTable")).Wait();

            Console.WriteLine("Done");
            Console.WriteLine();


            using (StreamWriter sw = new StreamWriter(resultsFormat.FormatWith("result.txt")))
            {
                var writers = new MultiWriter(sw, Console.Out);
                writers.WriteLine("Edge Count: {0}", data.DataflowGraph.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.DataflowGraph.Nodes.Where(node => data.PipTypes[node] == PipType.Process && data.StartTimes[node] != 0).Count());

                File.WriteAllLines(resultsFormat.FormatWith("actual.durations.csv"), data.Spans.Where(ps => data.PipTypes[ps.Id] == PipType.Process).Select(ps => string.Join(",", data.GetName(ps.Id), ps.Duration.ToMinutes().ToString())));
                File.WriteAllLines(resultsFormat.FormatWith("actual.durations.txt"), data.Spans.Select(ps => ps.Duration.ToMinutes().ToString()));
                File.WriteAllLines(resultsFormat.FormatWith("actual.starts.txt"), data.Spans.Select(ps => ps.StartTime.ToMinutes().ToString()));
                File.WriteAllLines(resultsFormat.FormatWith("actual.ends.txt"), data.Spans.Select(ps => ps.EndTime.ToMinutes().ToString()));

                CreateSpanImage(resultsFormat.FormatWith("actual.png"), data.Spans, data.TotalDuration, Math.Max(data.ActualConcurrency, 1));

                SimulationResult actualSimulation = null;
                if (true)
                {
                    Console.WriteLine("Simulating actual build");
                    actualSimulation = new SimulationResult(data, data.AggregateCosts);
                    actualSimulation.Simulate((uint)data.ActualConcurrency);

                    File.WriteAllLines(resultsFormat.FormatWith("actualSimulation.durations.txt"), actualSimulation.GetSpans().Select(ps => ps.Duration.ToMinutes().ToString()));
                    File.WriteAllLines(resultsFormat.FormatWith("actualSimulation.starts.txt"), actualSimulation.GetSpans().Select(ps => ps.StartTime.ToMinutes().ToString()));
                    File.WriteAllLines(resultsFormat.FormatWith("actualSimulation.ends.txt"), actualSimulation.GetSpans().Select(ps => ps.EndTime.ToMinutes().ToString()));

                    string csvFormat = "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}";


                    File.WriteAllLines(resultsFormat.FormatWith("actualSimulation.txt"), new string[] { csvFormat.FormatWith("Id", "Thread", "Minimum Start Time", "Start Time", "End Time", "Duration", "Incoming", "Outgoing") }.Concat(actualSimulation.GetSpans().Select(ps =>
                                                                                                                                                                                                                                                                             csvFormat.FormatWith(
                                                                                                                                                                                                                                                                                 ps.Id.Value,
                                                                                                                                                                                                                                                                                 ps.Thread,
                                                                                                                                                                                                                                                                                 actualSimulation.MinimumStartTimes[ps.Id].ToMinutes(),
                                                                                                                                                                                                                                                                                 ps.StartTime.ToMinutes(),
                                                                                                                                                                                                                                                                                 ps.EndTime.ToMinutes(),
                                                                                                                                                                                                                                                                                 ps.Duration.ToMinutes(),
                                                                                                                                                                                                                                                                                 data.DataflowGraph.GetIncomingEdgesCount(ps.Id),
                                                                                                                                                                                                                                                                                 data.DataflowGraph.GetIncomingEdgesCount(ps.Id)))));

                    CreateSimulationImage(actualSimulation, resultsFormat.FormatWith("actualSimulation.png"));

                    Console.WriteLine("Done");
                }

                Console.WriteLine();


                writers.WriteLine("Actual Total Build Time: {0} min", data.TotalDuration.ToMinutes());
                writers.WriteLine("Actual Concurrency: {0}", data.ActualConcurrency);
                if (actualSimulation != null)
                {
                    writers.WriteLine("Simulated total build time (using actual concurrency): {0} min", actualSimulation.TotalTime.ToMinutes());
                }

                int nameWidth;

                int   count            = 0;
                ulong criticalPathCost = 0;
                foreach (var p in data.GetSortedPips(20, true, n => data.PipTypes[n] == PipType.Process, n => data.AggregateCosts[n]))
                {
                    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}>", data.GetName(n).PadLeft(nameWidth), data.Durations[n].ToMinutes(), data.PipIds[n], data.PipTypes[n]))));
                }


                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]);
                }

                int    simulationCount = 1;
                int    increment       = 70;
                int?[] threadCounts    = new int?[simulationCount];
                threadCounts[0] = 60;
                //threadCounts[0] = 60;
                //threadCounts[4] = 330;
                //threadCounts[5] = 400;
                //threadCounts[6] = 470;
                SimulationResult[] results = new SimulationResult[simulationCount];
                Parallel.For(0, simulationCount, i =>
                {
                    var threadCount = threadCounts[i] ?? ((i + 1) * increment);
                    Console.WriteLine("Simulating {0}...", threadCount);
                    SimulationResult result = new SimulationResult(data, data.AggregateCosts);
                    result.Simulate((uint)threadCount);
                    results[i] = result;
                    Console.WriteLine("Done {0}", threadCount);

                    //Console.WriteLine("Simulating adjusted{0}...", threadCount);
                    //SimulationResult adjusted = new SimulationResult(data, data.ComputeAggregateCosts(result.GetAdjustedDurations(criticalPathCost)));
                    //result.Simulate((uint)threadCount);
                    //results[i + simulationCount] = result;
                    //Console.WriteLine("Done adjusted {0}", threadCount);

                    //i = i + (results.Length / 2);

                    //Console.WriteLine("Simulating {0}...", i);
                    //SimulationResult adjusted = new SimulationResult(data, result.EndTimes);
                    //adjusted.Simulate((uint)result.Threads.Count);
                    //results[i] = adjusted;
                    //Console.WriteLine("Done {0}", i);
                });

                results = results.OrderBy(s => s.Threads.Count).ToArray();

                string format = "{0}, {1}, {5}, {6}";
                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
                                  "Average Utilization",           // 5
                                  "Max Path Length",               // 6
                                  "Executed Pips"                  // 7
                                  );

                for (int i = 0; i < results.Length; i++)
                {
                    var result = results[i];
                    writers.WriteLine(format,
                                      result.Threads.Count,
                                      result.TotalTime.ToMinutes(),
                                      result.CriticalPath.Executions.Count,
                                      result.CriticalPath.Executions.Last().Id.Value,
                                      result.CriticalPath.IdleTime.ToMinutes(),
                                      Math.Round((double)result.TotalActiveTime / (double)((ulong)result.Threads.Count * result.TotalTime), 3),
                                      result.Threads.Select(t => t.Executions.Count).Max(),
                                      result.Threads.Select(t => t.Executions.Count).Sum());

                    CreateSimulationImage(result, resultsFormat.FormatWith("simulation.{0}.png".FormatWith(result.Threads.Count)));
                }
            }
        }
Beispiel #3
0
        public ConcurrentNodeDictionary <ulong> ComputeAggregateCosts(ConcurrentNodeDictionary <ulong> durations)
        {
            ConcurrentNodeDictionary <ulong> aggregateCosts = new ConcurrentNodeDictionary <ulong>(true);

            List <NodeId> sortedNodes = new List <NodeId>();

            sortedNodes.AddRange(DataflowGraph.Nodes);
            sortedNodes.Sort((n1, n2) => - DataflowGraph.GetNodeHeight(n1).CompareTo(DataflowGraph.GetNodeHeight(n2)));
            foreach (var node in sortedNodes)
            {
                //int maxConeConcurrency = 0;
                ulong  aggregateCost = 0;
                NodeId maxChild      = NodeId.Invalid;
                foreach (var outgoing in DataflowGraph.GetOutgoingEdges(node))
                {
                    if (aggregateCosts[outgoing.OtherNode].Max(ref aggregateCost) || !maxChild.IsValid())
                    {
                        maxChild = outgoing.OtherNode;
                    }
                }

                aggregateCost       += durations[node];
                aggregateCosts[node] = aggregateCost;
            }

            return(aggregateCosts);
        }