コード例 #1
0
ファイル: PipExecutionData.cs プロジェクト: uilit/BuildXL
        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)
            {
                ulong aggregateCost = 0;
                foreach (var incoming in DataflowGraph.GetIncomingEdges(node))
                {
                    BottomUpAggregateCosts[incoming.OtherNode].Max(ref aggregateCost);
                }

                aggregateCost += Durations[node];
                BottomUpAggregateCosts[node] = aggregateCost;
            }

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

                FormattedSemistableHashes[node] = CachedGraph.PipTable.GetFormattedSemiStableHash(node.ToPipId());
                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];
            }
        }
コード例 #2
0
        /// <summary>
        /// Exports the contents of the given pip graph. It is expected to no longer change as of the start of this call.
        /// </summary>
        public override int Analyze()
        {
            DgmlWriter writer = new DgmlWriter();

            Dictionary <PipId, PipReference> concretePipValues = new Dictionary <PipId, PipReference>();

            HashSet <PipReference> allValuePips = new HashSet <PipReference>(PipGraph.RetrievePipReferencesOfType(PipType.Value));

            foreach (var valuePip in allValuePips)
            {
                foreach (var incoming in DataflowGraph.GetIncomingEdges(valuePip.PipId.ToNodeId()))
                {
                    if (!PipTable.GetPipType(incoming.OtherNode.ToPipId()).IsMetaPip())
                    {
                        concretePipValues[valuePip.PipId] = valuePip;
                    }
                }
            }

            foreach (var concretePipValue in concretePipValues.Values)
            {
                var value = ((ValuePip)concretePipValue.HydratePip()).Symbol.ToString(SymbolTable);
                writer.AddNode(new DgmlWriter.Node(concretePipValue.PipId.ToString(), value));

                foreach (var incoming in DataflowGraph.GetIncomingEdges(concretePipValue.PipId.ToNodeId()))
                {
                    var incomingId = incoming.OtherNode.ToPipId();
                    if (concretePipValues.ContainsKey(incomingId))
                    {
                        writer.AddLink(new DgmlWriter.Link(
                                           incomingId.ToString(),
                                           concretePipValue.PipId.ToString(),
                                           label: null));
                    }
                }
            }

            writer.Serialize(m_dgmlFilePath);

            return(0);
        }
コード例 #3
0
        public override int Analyze()
        {
            Console.WriteLine($"Analyzing");

            m_block.Complete();
            m_block.CompletionAsync().GetAwaiter().GetResult();

            Console.WriteLine($"Writing Graph");

            foreach (var pip in PipGraph.RetrieveAllPips())
            {
                var serializedPip = pip;
                var nodeId        = pip.PipId.ToNodeId();

                bool addEdges = true;
                if (pip.PipType == PipType.Process)
                {
                    var entry = GetEntry(pip.PipId);
                    serializedPip = entry.Process;
                    addEdges      = !entry.AddedEdges;
                }

                if (addEdges && AddEdgesForPips)
                {
                    using (var scope = m_mutableGraph.AcquireExclusiveIncomingEdgeScope(nodeId))
                    {
                        foreach (var edge in DataflowGraph.GetIncomingEdges(nodeId))
                        {
                            scope.AddEdge(edge.OtherNode, edge.IsLight);
                        }
                    }
                }

                serializedPip.ResetPipIdForTesting();
                m_pipTable.Add(nodeId.Value, serializedPip);
            }

            m_mutableGraph.Seal();

            CachedGraph.Serializer.SerializeToFileAsync(
                GraphCacheFile.DirectedGraph,
                m_mutableGraph.Serialize,
                Path.Combine(OutputFilePath, nameof(GraphCacheFile.DirectedGraph)))
            .GetAwaiter().GetResult();

            CachedGraph.Serializer.SerializeToFileAsync(
                GraphCacheFile.PipTable,
                w => m_pipTable.Serialize(w, Environment.ProcessorCount),
                Path.Combine(OutputFilePath, nameof(GraphCacheFile.PipTable)))
            .GetAwaiter().GetResult();

            CachedGraph.Serializer.SerializeToFileAsync(
                GraphCacheFile.PipGraphId,
                PipGraph.SerializeGraphId,
                Path.Combine(OutputFilePath, nameof(GraphCacheFile.PipGraphId)))
            .GetAwaiter().GetResult();

            Console.WriteLine($"Simulating [Reading]");
            var simulator = new BuildSimulatorAnalyzer(Input);

            simulator.Increment = SimulatorIncrement ?? simulator.Increment;
            simulator.ExecutionData.DataflowGraph = m_mutableGraph;

            simulator.OutputDirectory = OutputFilePath;
            simulator.ReadExecutionLog();

            Console.WriteLine($"Simulating [Analyzing]");
            simulator.Analyze();

            Console.WriteLine($"Blocking Dependency Analysis");

            DisplayTable <DepColumn> depTable = new DisplayTable <DepColumn>(" , ");

            foreach (var pipId in PipTable.Keys)
            {
                var pipType = PipTable.GetPipType(pipId);
                if (pipType == PipType.Process)
                {
                    var entry = GetEntry(pipId);
                    (PipId node, ulong cost)maxConsumedDependency = default;
                    (PipId node, ulong cost)maxDependency         = default;

                    foreach (var dep in entry.PipDependencies)
                    {
                        var cost = simulator.ExecutionData.BottomUpAggregateCosts[dep.Key.ToNodeId()];
                        if (!maxDependency.node.IsValid || cost > maxDependency.cost)
                        {
                            maxDependency = (dep.Key, cost);
                        }

                        if (dep.Value != null && dep.Value.HasFlag(ContentFlag.Consumed))
                        {
                            if (!maxConsumedDependency.node.IsValid || cost > maxConsumedDependency.cost)
                            {
                                maxConsumedDependency = (dep.Key, cost);
                            }
                        }
                    }

                    depTable.NextRow();
                    depTable.Set(DepColumn.Id, $"{entry.SpecFileName}-{entry.Identifier}");
                    depTable.Set(DepColumn.MaxConsumedDependency, ToString(maxConsumedDependency.node));
                    depTable.Set(DepColumn.MaxConsumedDependencyChainCost, maxConsumedDependency.cost.ToMinutes());
                    depTable.Set(DepColumn.MaxDependency, ToString(maxDependency.node));
                    depTable.Set(DepColumn.MaxDependencyChainCost, maxDependency.cost.ToMinutes());
                }
                else if (pipType == PipType.SealDirectory &&
                         !PipTable.GetSealDirectoryKind(pipId).IsSourceSeal() &&
                         !IsSourceOnlySeal(pipId))
                {
                    var seal  = (SealDirectory)GetPip(pipId);
                    var entry = GetEntry(seal.Directory);
                    (PipId node, ulong cost)maxDependency = default;

                    foreach (var dep in DataflowGraph.GetIncomingEdges(pipId.ToNodeId()))
                    {
                        var cost = simulator.ExecutionData.BottomUpAggregateCosts[dep.OtherNode];
                        if (!maxDependency.node.IsValid || cost > maxDependency.cost)
                        {
                            maxDependency = (dep.OtherNode.ToPipId(), cost);
                        }
                    }

                    depTable.NextRow();
                    depTable.Set(DepColumn.Id, $"{entry.SpecFileName}-{entry.Identifier} ({entry.FileCount} files)");
                    depTable.Set(DepColumn.MaxDependency, ToString(maxDependency.node));
                    depTable.Set(DepColumn.MaxDependencyChainCost, maxDependency.cost.ToMinutes());
                    depTable.Set(DepColumn.Directory, seal.DirectoryRoot.ToString(PathTable));
                }
            }

            using (var blockAnalysisWriter = new StreamWriter(Path.Combine(OutputFilePath, "blockAnalysis.txt")))
            {
                depTable.Write(blockAnalysisWriter);
            }

            m_writer.Dispose();

            Console.WriteLine($"Analyzing complete");

            return(0);
        }
コード例 #4
0
        public override int Analyze()
        {
            Console.WriteLine("Writing failed pip info to '{0}'.", OutputFilePath);
            using (var streamWriter = new StreamWriter(OutputFilePath))
                using (JsonWriter writer = new JsonTextWriter(streamWriter))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName("Mounts");
                    {
                        writer.WriteStartObject();

                        var mountPathExpander = m_mountPathExpander ?? CachedGraph.MountPathExpander;
                        foreach (var mountRoot in mountPathExpander.GetAllRoots())
                        {
                            var mount = mountPathExpander.GetSemanticPathInfo(mountRoot);
                            writer.WritePropertyName(mount.RootName.ToString(StringTable));
                            writer.WriteValue(mountRoot.ToString(PathTable));
                        }

                        writer.WriteEndObject();
                    }

                    writer.WritePropertyName("FileInfo");
                    {
                        writer.WriteStartObject();

                        foreach (var fileEntry in m_fileToConsumerMap)
                        {
                            var file      = fileEntry.Key;
                            var consumers = fileEntry.Value;
                            var path      = ToDisplayFilePath(file);
                            if (path != null)
                            {
                                writer.WritePropertyName(path, true);
                                {
                                    writer.WriteStartArray();

                                    foreach (var consumer in consumers)
                                    {
                                        writer.WriteValue(ToDisplayString(consumer));
                                    }

                                    writer.WriteEndArray();
                                }
                            }
                        }

                        writer.WriteEndObject();
                    }

                    writer.WritePropertyName("PipGraph");
                    {
                        writer.WriteStartObject();

                        m_failedPipsClosure.UnsafeReset();
                        writer.WritePropertyName("root");
                        {
                            writer.WriteStartArray();

                            foreach (var failedPip in m_failedPips)
                            {
                                writer.WriteValue(ToDisplayString(failedPip));
                            }

                            writer.WriteEndArray();
                        }

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

                        nodeVisitor.VisitTransitiveDependencies(m_failedPips.Select(p => p.ToNodeId()), m_failedPipsClosure, visitNode: node =>
                        {
                            dependencyBuffer.Clear();
                            foreach (var dependencyEdge in DataflowGraph.GetIncomingEdges(node))
                            {
                                if (PipTable.GetPipType(dependencyEdge.OtherNode.ToPipId()) != PipType.HashSourceFile)
                                {
                                    dependencyBuffer.Add(dependencyEdge.OtherNode);
                                }
                            }

                            if (dependencyBuffer.Count != 0)
                            {
                                writer.WritePropertyName(ToDisplayString(node.ToPipId()));
                                {
                                    writer.WriteStartArray();

                                    foreach (var dependencyNode in dependencyBuffer)
                                    {
                                        writer.WriteValue(ToDisplayString(dependencyNode.ToPipId()));
                                    }

                                    writer.WriteEndArray();
                                }
                            }

                            return(true);
                        });

                        writer.WriteEndObject();
                    }

                    writer.WriteEndObject();
                }

            return(0);
        }
コード例 #5
0
        /// <summary>
        /// Generate the output of failure data
        /// Failed pips + process chain : This points to the tool that failed.
        /// Set of dependencies diff contains: source and output changes. Which of those are directe referenced
        ///
        /// </summary>
        /// <param name="isDiff">There is diff data from another log</param>
        private void GenerateOutput(bool isDiff)
        {
            Console.WriteLine("Writing failed pip info to '{0}'.", OutputFilePath);
            using (var streamWriter = new StreamWriter(OutputFilePath))
                using (JsonWriter writer = new JsonTextWriter(streamWriter))
                {
                    writer.WriteStartObject();

                    writer.WritePropertyName("Mounts");
                    {
                        writer.WriteStartObject();

                        var mountPathExpander = m_mountPathExpander ?? CachedGraph.MountPathExpander;
                        foreach (var mountRoot in mountPathExpander.GetAllRoots())
                        {
                            var mount = mountPathExpander.GetSemanticPathInfo(mountRoot);
                            writer.WritePropertyName(mount.RootName.ToString(StringTable));
                            writer.WriteValue(mountRoot.ToString(PathTable));
                        }

                        writer.WriteEndObject();
                    }

                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WritePropertyName("Failures");
                    {
                        writer.WriteStartArray();

                        foreach (var failedPip in m_failedPips)
                        {
                            var pip = (Process)m_pipTable.HydratePip(failedPip, PipQueryContext.ViewerAnalyzer);
                            writer.WriteWhitespace(Environment.NewLine);
                            writer.WriteStartObject();
                            // prints the semistable hash.
                            WritePropertyAndValue(writer, "PipId", ToDisplayString(failedPip));
                            WritePropertyAndValue(writer, "Working Directory", ToDisplayFilePath(pip.WorkingDirectory));

                            var provenance = pip.Provenance;
                            WritePropertyAndValue(
                                writer,
                                "Qualifier",
                                provenance != null ? PipGraph.Context.QualifierTable.GetCanonicalDisplayString(provenance.QualifierId) : string.Empty);
                            WritePropertyAndValue(
                                writer,
                                "OutputValueSymbol",
                                provenance != null ? provenance.OutputValueSymbol.ToString(SymbolTable) : string.Empty);

                            var pipPerformance = m_pipPerformance[pip.PipId.Value];
                            WritePropertyAndValue(writer, "PeakMemoryUsageMb", pipPerformance.PeakMemoryUsageMb.ToString());
                            WritePropertyAndValue(writer, "NumberOfProcesses", pipPerformance.NumberOfProcesses.ToString());
                            WritePropertyAndValue(
                                writer,
                                "FileMonitoringViolationsNotWhitelisted",
                                pipPerformance.FileMonitoringViolations.NumFileAccessViolationsNotWhitelisted.ToString());

                            if (isDiff)
                            {
                                WritePropertyAndValue(writer, "NumberOfImputChanges", GetDependencyChangesForPip(pip).ToString());
                            }

                            if (m_pipDependencyViolationEventData.TryGetValue(pip.PipId, out var pipDependencyViolationEvent))
                            {
                                foreach (var data in pipDependencyViolationEvent)
                                {
                                    WritePropertyAndValue(writer, "DependencyViolationType", data.ViolationType.ToString());
                                    WritePropertyAndValue(writer, "Path causing violation", ToDisplayFilePath(data.Path));
                                }
                            }

                            WriteProcessChain(writer, pip);
                            // TODO : Are environment variables usefull for analysis
                            //      : Are are all the failures required or choose count as cmd line arg to take top n
                            writer.WriteWhitespace(Environment.NewLine);
                            writer.WriteEndObject();
                        }

                        writer.WriteEndArray();
                    }

                    writer.WriteWhitespace(Environment.NewLine);

                    var fileToConsumerMap = m_fileToConsumerMap;
                    var propertyName      = "FileInfo";
                    if (isDiff)
                    {
                        propertyName      = "FileInfoDiff";
                        fileToConsumerMap = m_fileToConsumerMapDiff;

                        // If any added dependencies add them to the output
                        if (m_fileToConsumerMapAdded.Count > 0)
                        {
                            WriteFileDependencies("FileInfoAdded", m_fileToConsumerMapAdded, writer);
                        }
                        // TODO:Add removed dependencies when compared to other log
                    }
                    WriteFileDependencies(propertyName, fileToConsumerMap, writer);

                    writer.WriteWhitespace(Environment.NewLine);
                    writer.WritePropertyName("PipGraph");
                    {
                        writer.WriteStartObject();

                        m_failedPipsClosure.UnsafeReset();
                        writer.WritePropertyName("root");
                        {
                            writer.WriteStartArray();

                            foreach (var failedPip in m_failedPips)
                            {
                                writer.WriteValue(ToDisplayString(failedPip));
                            }

                            writer.WriteEndArray();
                        }

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

                        nodeVisitor.VisitTransitiveDependencies(
                            m_failedPips.Select(p => p.ToNodeId()),
                            m_failedPipsClosure,
                            visitNode: node =>
                        {
                            dependencyBuffer.Clear();
                            foreach (var dependencyEdge in DataflowGraph.GetIncomingEdges(node))
                            {
                                if (PipTable.GetPipType(dependencyEdge.OtherNode.ToPipId()) != PipType.HashSourceFile)
                                {
                                    dependencyBuffer.Add(dependencyEdge.OtherNode);
                                }
                            }

                            if (dependencyBuffer.Count != 0)
                            {
                                writer.WritePropertyName(ToDisplayString(node.ToPipId()));
                                {
                                    writer.WriteStartArray();

                                    foreach (var dependencyNode in dependencyBuffer)
                                    {
                                        writer.WriteValue(ToDisplayString(dependencyNode.ToPipId()));
                                    }

                                    writer.WriteEndArray();
                                }
                            }

                            return(true);
                        });

                        writer.WriteEndObject();
                    }

                    writer.WriteEndObject();
                }
        }