コード例 #1
0
        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);
        }
コード例 #2
0
ファイル: ProjectCollector.cs プロジェクト: kittinap/kunnjae
        /// <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);
        }
コード例 #3
0
        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);
                        }
                    }
                }
            });
        }
コード例 #4
0
        /// <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);
        }