Esempio n. 1
0
        private XElement CreateGraph(ActiveWorkerTracker workTracker, TimeSpan?durationTime, int?durationDepth, int graphSize, string title)
        {
            var entries = workTracker.Entries.ToArray();

            int  maxCount = entries.Max(e => e.Count);
            long maxTime  = entries.Last().Time.Ticks;

            long lastTime         = 0;
            var  polyLine1Builder = new StringBuilder();

            var count     = entries.Length;
            var meanIndex = (count / 2) + (count % 2);

            if (meanIndex >= count)
            {
                meanIndex = 0;
            }

            var mean = entries[meanIndex].Count;

            var sum         = 0L;
            var weightedSum = 0L;
            var stdDevSq    = 0L;

            foreach (var entry in entries)
            {
                polyLine1Builder.AppendLine($"{GetPoint(graphSize, entry.Count, maxCount)},{GetPoint(graphSize, lastTime, maxTime)}");
                polyLine1Builder.AppendLine($"{GetPoint(graphSize, entry.Count, maxCount)},{GetPoint(graphSize, entry.Time.Ticks, maxTime)}");

                weightedSum += entry.Count * (entry.Time.Ticks - lastTime);
                sum         += entry.Count;
                stdDevSq    += (entry.Count - mean) * (entry.Count - mean);

                lastTime = entry.Time.Ticks;
            }

            return(new XElement(
                       "div",
                       new XElement("h3", title),
                       new XElement(
                           "div",
                           m_html.CreateRow("Parellalism (max)", maxCount),
                           m_html.CreateRow("Parellalism (avg)", Convert.ToInt64(sum / (double)count)),
                           m_html.CreateRow("Parellalism (weighted avg)", Convert.ToInt64(weightedSum / (double)maxTime)),
                           m_html.CreateRow("Parellalism (mean)", mean),
                           m_html.CreateRow("Parellalism (stdDev)", Convert.ToInt64(Math.Sqrt(stdDevSq))),
                           durationTime.HasValue ? m_html.CreateRow("Duration (time)", durationTime.Value) : null,
                           durationDepth.HasValue ? m_html.CreateRow("Duration (depth)", durationDepth.Value) : null),
                       new XElement(
                           "svg",
                           new XAttribute("version", "1.1"),
                           new XAttribute("width", graphSize),
                           new XAttribute("height", graphSize),
                           new XAttribute("style", "boder: 1px solid black"),
                           new XElement(
                               "polyline",
                               new XAttribute("fill", "none"),
                               new XAttribute("stroke", "black"),
                               new XAttribute("stroke-widt", "2"),
                               new XAttribute("points", $"0,0 0,{graphSize}, {graphSize},{graphSize} {graphSize},0 0,0")),
                           new XElement(
                               "polyline",
                               new XAttribute("fill", "none"),
                               new XAttribute("stroke", "green"),
                               new XAttribute("stroke-widt", "3"),
                               new XAttribute("points", polyLine1Builder.ToString())))));
        }
Esempio n. 2
0
        private XElement RenderUsageStatistics(BuildXLStats stats)
        {
            var actualUsage = new ActiveWorkerTracker();

            foreach (var kv in m_pipExecutionPerf.Values)
            {
                actualUsage.AddEntry(kv.ExecutionStart - m_firstPip, kv.ExecutionStop - m_firstPip);
            }

            int numberOfPips = CachedGraph.PipTable.Count + 1; // pipIds start at 1;

            Console.WriteLine("Processing nr of pipzies: " + numberOfPips);
            var refCounts = new int[numberOfPips];
            var startTime = new TimeSpan[numberOfPips];
            var startTick = new int[numberOfPips];
            var duration  = new TimeSpan[numberOfPips];

            var maxSimulationTick = 0;
            var maxSimulationTime = TimeSpan.Zero;
            var minActualStart    = DateTime.MaxValue;
            var maxActualStop     = DateTime.MinValue;

            var readyQueue = new Queue <PipId>();

            // build RunState
            foreach (var pipId in CachedGraph.PipTable.Keys)
            {
                var pipIdx = pipId.Value;

                int incommingCount = CachedGraph.DirectedGraph.GetIncomingEdgesCount(pipId.ToNodeId());
                refCounts[pipIdx] = incommingCount;

                if (incommingCount == 0)
                {
                    startTime[pipIdx] = TimeSpan.Zero;
                    startTick[pipIdx] = 0;

                    readyQueue.Enqueue(pipId);
                }

                if (m_pipExecutionPerf.ContainsKey(pipId))
                {
                    var executionStart = m_pipExecutionPerf[pipId].ExecutionStart;
                    var executionStop  = m_pipExecutionPerf[pipId].ExecutionStop;

                    minActualStart = minActualStart < executionStart ? minActualStart : executionStart;
                    maxActualStop  = maxActualStop > executionStop ? maxActualStop : executionStop;

                    duration[pipIdx] = executionStop - executionStart;
                }
                else
                {
                    duration[pipIdx] = TimeSpan.Zero;
                }
            }

            while (readyQueue.Count != 0)
            {
                var pipId = readyQueue.Dequeue();

                var pipEndTime = startTime[pipId.Value] + duration[pipId.Value];
                var pipEndTick = startTick[pipId.Value] + 1;

                maxSimulationTick = Math.Max(maxSimulationTick, pipEndTick);
                maxSimulationTime = maxSimulationTime > pipEndTime ? maxSimulationTime : pipEndTime;

                foreach (var dependent in CachedGraph.PipGraph.RetrievePipReferenceImmediateDependents(pipId))
                {
                    var depId    = dependent.PipId;
                    var depIdx   = depId.Value;
                    var curCount = refCounts[depIdx];
                    Contract.Assert(curCount > 0);
                    curCount--;
                    refCounts[depIdx] = curCount;

                    if (curCount == 0)
                    {
                        startTime[depIdx] = pipEndTime;
                        startTick[depIdx] = pipEndTick;

                        readyQueue.Enqueue(depId);
                    }
                }
            }

            var simulateWithActualTime = new ActiveWorkerTracker();
            var simulateWithEqualTime  = new ActiveWorkerTracker();

            for (int i = 1; i < numberOfPips; i++)
            {
                if (CachedGraph.PipTable.GetPipType(new PipId((uint)i)) != PipType.Process)
                {
                    // Skip pips other than HashSourceFile pips
                    continue;
                }

                simulateWithActualTime.AddEntry(startTime[i], startTime[i] + duration[i]);
                simulateWithEqualTime.AddEntry(TimeSpan.FromSeconds(startTick[i]), TimeSpan.FromSeconds(startTick[i] + 1));
            }

            int graphSize = 1000;

            var warnings = new XElement("div");

            long?processPipCacheHits = stats.GetValue("ProcessPipCacheHits");

            if (processPipCacheHits > 0)
            {
                warnings.Add(new XElement("div", new XAttribute("class", "warning"), $"Warning: This build had '{stats["ProcessPipCacheHits"]}' cache hits. Therefore the following graphs are not reliable for full graph analysis as those pips have a much shorter execution time than normal if they were cache hits. You can run the build with '/incremental-' to force cache misses."));
            }

            long?pipsFailed = stats.GetValue("PipsFailed");

            if (pipsFailed > 0)
            {
                warnings.Add(new XElement("div", new XAttribute("class", "warning"), $"Warning: This build had '{stats["PipsFailed"]}' failed pips. Therefore the following graphs are not complete for analysis. The failed pips as well as the pips that transitively depend on them will not be visible nor measured in these graphs "));
            }

            return(new XElement(
                       "div",
                       warnings,
                       CreateGraph(
                           actualUsage,
                           durationTime: maxActualStop - minActualStart,
                           durationDepth: null,
                           graphSize: graphSize,
                           title: "Actual start times & durations"),
                       CreateGraph(
                           simulateWithActualTime,
                           durationTime: maxSimulationTime,
                           durationDepth: maxSimulationTick,
                           graphSize: graphSize,
                           title: "Simulate with infinite resources and actual durations"),
                       CreateGraph(
                           simulateWithEqualTime,
                           durationTime: null,
                           durationDepth: maxSimulationTick,
                           graphSize: graphSize,
                           title: "Simulate with infinite resources and equal cost per pip")));
        }