public static PipStrings CreatePipStrings(Pip pip, CachedGraph cachedGraph) { PipStrings result; if (pip.PipType == PipType.Process) { result = new PipStrings(pip as Process, cachedGraph); } else if (pip.PipType == PipType.CopyFile) { result = new PipStrings(pip as CopyFile, cachedGraph); } else if (pip.PipType == PipType.WriteFile) { result = new PipStrings(pip as WriteFile, cachedGraph); } else { result = new PipStrings(); } result.m_pip = pip; // Tags { var stringTable = cachedGraph.Context.StringTable; foreach (var tag in pip.Tags) { result.m_tags.Add(tag.ToString(stringTable)); } } return(result); }
/// <summary> /// Note: ThreadPool is not used in this implementation because it doesn't fully saturate the CPU /// for some reason. This implementation ensures that the CPU is fully saturated. On small graphs, /// I've noticed a 1.5x speedup. On bigger graphs, there is still some perf benefit but not as much. /// </summary> private List <DifferentPipPair> FindDifferentPipPairs(IEnumerable <KeyValuePair <PipId, PipId> > matchingPips) { var differentPipPairComparer = new DifferentPipPairComparer(); var result = new ConcurrentBag <DifferentPipPair>(); var matchingPipsQueue = new ConcurrentQueue <KeyValuePair <PipId, PipId> >(matchingPips); var threadCount = (int)(Environment.ProcessorCount * 1.25); var threads = Enumerable.Range(0, threadCount).Select(_ => new Thread(() => { while (matchingPipsQueue.TryDequeue(out var pipPair)) { var firstPip = m_firstGraphAnalysisInput.CachedGraph.PipGraph.GetPipFromPipId(pipPair.Key); var secondPip = m_secondGraphAnalysisInput.CachedGraph.PipGraph.GetPipFromPipId(pipPair.Value); var firstPipStrings = PipStrings.CreatePipStrings(firstPip, m_firstGraphAnalysisInput.CachedGraph); var secondPipStrings = PipStrings.CreatePipStrings(secondPip, m_secondGraphAnalysisInput.CachedGraph); var differentPipPair = firstPipStrings.GetDifferencesIfAny(secondPipStrings); if (differentPipPair != null) { result.Add(differentPipPair); } } }) ).ToList(); threads.ForEach(t => t.Start()); threads.ForEach(t => t.Join()); return(result .OrderBy(pipPair => pipPair, differentPipPairComparer) .ToList()); }
/// <summary> /// If there are no differences, then null is returned /// </summary> public DifferentPipPair GetDifferencesIfAny(PipStrings other) { var result = new DifferentPipPair(); result.FirstPip = m_pip.PipId; result.SecondPip = other.m_pip.PipId; if (!m_inputFiles.SetEquals(other.m_inputFiles)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.InputFiles); } if (!m_outputFiles.SetEquals(other.m_outputFiles)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.OutputFiles); } if (!m_opaqueInputDirs.SetEquals(other.m_opaqueInputDirs)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.OpaqueInputDirs); } if (!m_opaqueOutputDirs.SetEquals(other.m_opaqueOutputDirs)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.OpaqueOutputDirs); } if (m_executable != other.m_executable) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.Executable); } if (m_stdInFile != other.m_stdInFile) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.StdInFile); } if (m_stdInData != other.m_stdInData) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.StdInData); } if (!m_envVars.SetEquals(other.m_envVars)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.EnvVars); } if (m_workingDir != other.m_workingDir) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.WorkingDir); } if (m_uniqueOutputDir != other.m_uniqueOutputDir) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.UniqueOutputDir); } if (m_tempDir != other.m_tempDir) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.TempDir); } if (m_arguments != other.m_arguments) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.Arguments); } if (!m_sealDirectoryInputs.SetEquals(other.m_sealDirectoryInputs)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.SealDirInputs); } if (!m_tags.SetEquals(other.m_tags)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.Tags); } if (!m_untrackedPaths.SetEquals(other.m_untrackedPaths)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.UntrackedPaths); } if (!m_untrackedScopes.SetEquals(other.m_untrackedScopes)) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.UntrackedScopes); } if (m_writeFileContents != other.m_writeFileContents) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.WriteFileContents); } if (m_writeFileEncoding != other.m_writeFileEncoding) { result.DiffReasons.Add(DifferentPipPair.DifferenceReason.WriteFileEncoding); } return(result.DiffReasons.Any() ? result : null); }