public void Test_ParallelAlgorithms_WhileNotEmpty_While() { var list = new int[] { 100, 4, 5, 56, 23, 2, 1, 0, -99, 456, 234, 11, 9999, 44, 2 }; //待研究 ParallelAlgorithms.WhileNotEmpty(list, (e1, e2) => e2(0)); Assert.IsTrue(true); }
/// <summary> /// Recursively goes down each directory and collects project files. The search stops in directories that contain /// a project configuration or a configuration file. /// </summary> private static void CollectAllPathsToProjectsRecursively(IFileSystem fileSystem, AbsolutePath pathToPackageDirectory, List <AbsolutePath> projects) { var pathTable = fileSystem.GetPathTable(); Action <AbsolutePath, Action <AbsolutePath> > collectPackages = (directory, adder) => { if (!IsWellKnownConfigurationFileExists(directory, pathTable, fileSystem)) { CollectAllPathsToProjects(fileSystem, directory, projects); var subDirectories = fileSystem.EnumerateDirectories(directory); foreach (var subDirectory in subDirectories) { adder(subDirectory); } } }; ParallelAlgorithms.WhileNotEmpty( fileSystem.EnumerateDirectories(pathToPackageDirectory), collectPackages); }
private void ParallelVisitNode(INode node, DiagnosticContext context) { ParallelAlgorithms.WhileNotEmpty(new[] { node }, (item, adder) => { // Only non-injected nodes are checked by the linter. if (item.IsInjectedForDScript()) { return; } Handle(item, context); using (var list = NodeWalker.GetChildrenFast(item)) { foreach (var child in list.Instance) { foreach (var e in child) { adder(e); } } } }); }
/// <summary> /// Gets nodes to schedule. /// </summary> /// <param name="scheduleDependents">If true, then include all transitive dependents of the explicitly scheduled nodes.</param> /// <param name="explicitlyScheduledNodes">Explicitly scheduled nodes.</param> /// <param name="forceSkipDepsMode">If not disabled, then skip dependencies. This corresponds to "dirty" build.</param> /// <param name="scheduleMetaPips">If true, metapips will be scheduled</param> /// <returns>Nodes to schedule.</returns> public GetScheduledNodesResult GetNodesToSchedule( bool scheduleDependents, IEnumerable<NodeId> explicitlyScheduledNodes, ForceSkipDependenciesMode forceSkipDepsMode, bool scheduleMetaPips) { int explicitlySelectedNodeCount; int explicitlySelectedProcessCount; int dirtyNodeCount; int dirtyProcessCount; int nonMaterializedNodeCount; int nonMaterializedProcessCount; int processesInBuildCone = 0; HashSet<NodeId> nodesToSchedule; VisitationTracker transitiveDependencyNodeFilter; using (m_counters.StartStopwatch(PipExecutorCounter.BuildSetCalculatorComputeBuildCone)) { var visitedNodes = new VisitationTracker(m_graph); nodesToSchedule = new HashSet<NodeId>(explicitlyScheduledNodes); explicitlySelectedNodeCount = nodesToSchedule.Count; explicitlySelectedProcessCount = nodesToSchedule.Count(IsProcess); // 1. Calculate dirty nodes. // The filter-passing set may include nodes which are dirty/clean and schedulable/not-schedulable (w.r.t. state). // We want stats on dirty vs. not-dirty, and want to drop anything not schedulable. // This step also marks dirty non-materialized nodes. CalculateDirtyNodes( nodesToSchedule, out dirtyNodeCount, out dirtyProcessCount, out nonMaterializedNodeCount, out nonMaterializedProcessCount); if (dirtyNodeCount == 0) { int duration = (int) m_counters.GetElapsedTime(PipExecutorCounter.BuildSetCalculatorComputeBuildCone).TotalMilliseconds; // Build cone is the same as the explicitly selected processes. Logger.Log.BuildSetCalculatorProcessStats( m_loggingContext, m_graph.Nodes.Count(IsProcess), explicitlySelectedProcessCount, explicitlySelectedProcessCount, explicitlySelectedProcessCount, 0, duration); Logger.Log.BuildSetCalculatorStats( m_loggingContext, 0, 0, explicitlySelectedNodeCount, explicitlySelectedProcessCount, nonMaterializedNodeCount, nonMaterializedProcessCount, duration, 0, 0, 0, 0); return GetScheduledNodesResult.CreateForNoOperationBuild(explicitlySelectedProcessCount); } // 2. Add transitive dependents of explicitly scheduled nodes (if requested). if (scheduleDependents) { m_visitor.VisitTransitiveDependents( nodesToSchedule, visitedNodes, node => { // Don't schedule dependents that are meta pips. These may artificially connect unrequested // pips since we will later schedule their dependencies. For example, this would cause // everything referenced by a spec file pip to be scheduled as a single unit. PipType pipType = GetPipType(node); if (!pipType.IsMetaPip()) { nodesToSchedule.Add(node); if (pipType == PipType.Process) { ++processesInBuildCone; } return true; } return false; }); } // At this point nodesToSchedule contains // (1) all nodes that are explicitly scheduled (explicitlyScheduledNodes), and // (2) if scheduleDependents is true, all dependents of (1) transitively. transitiveDependencyNodeFilter = visitedNodes; // 3. Collect/visit transitive dependencies, but don't put it in nodesToSchedule. transitiveDependencyNodeFilter.UnsafeReset(); // The code below essentially does m_visitor.VisitTransitiveDependencies(nodesToSchedule, transitiveDependencyNodeFilter, node => true), but in parallel. foreach (var nodeId in nodesToSchedule) { if (transitiveDependencyNodeFilter.MarkVisited(nodeId)) { if (IsProcess(nodeId)) { ++processesInBuildCone; } } } ParallelAlgorithms.WhileNotEmpty( nodesToSchedule, (node, add) => { foreach (Edge inEdge in m_graph.GetIncomingEdges(node)) { if (visitedNodes.MarkVisited(inEdge.OtherNode)) { add(inEdge.OtherNode); if (IsProcess(inEdge.OtherNode)) { Interlocked.Increment(ref processesInBuildCone); } } } }); // At this point nodesToSchedule hasn't change from step 2. // But now, transitiveDependencyNodeFilter have already marked all nodes in nodesToSchedule, plus // their dependencies transitively. } IEnumerable<NodeId> scheduledNodes; var mustExecute = new HashSet<NodeId>(); var stats = new BuildSetCalculatorStats(); var metaPipCount = 0; using (m_counters.StartStopwatch(PipExecutorCounter.BuildSetCalculatorGetNodesToSchedule)) { scheduledNodes = GetNodesToSchedule( nodesToSchedule, transitiveDependencyNodeFilter, forceSkipDepsMode, scheduleMetaPips, mustExecute, stats, ref metaPipCount); } int buildConeDuration = (int) m_counters.GetElapsedTime(PipExecutorCounter.BuildSetCalculatorComputeBuildCone).TotalMilliseconds; int getScheduledNodesDuration = (int) m_counters.GetElapsedTime(PipExecutorCounter.BuildSetCalculatorGetNodesToSchedule).TotalMilliseconds; int scheduledProcessCount = scheduledNodes.Count(IsProcess); Logger.Log.BuildSetCalculatorProcessStats( m_loggingContext, m_graph.Nodes.Count(IsProcess), explicitlySelectedProcessCount, processesInBuildCone, (processesInBuildCone - scheduledProcessCount) + stats.CleanMaterializedProcessFrontierCount, scheduledProcessCount, buildConeDuration + getScheduledNodesDuration); Logger.Log.BuildSetCalculatorStats( m_loggingContext, dirtyNodeCount, dirtyProcessCount, explicitlySelectedNodeCount, explicitlySelectedProcessCount, nonMaterializedNodeCount, nonMaterializedProcessCount, buildConeDuration, scheduledNodes.Count(), scheduledProcessCount, metaPipCount, getScheduledNodesDuration); int incrementalSchedulingCacheHits = forceSkipDepsMode == ForceSkipDependenciesMode.Disabled ? (processesInBuildCone - scheduledProcessCount + stats.CleanMaterializedProcessFrontierCount) : 0; return new GetScheduledNodesResult( scheduledNodes: scheduledNodes, mustExecuteNodes: mustExecute, incrementalSchedulingCacheHitProcesses: incrementalSchedulingCacheHits, cleanMaterializedProcessFrontierCount: forceSkipDepsMode == ForceSkipDependenciesMode.Disabled ? stats.CleanMaterializedProcessFrontierCount : 0); }