示例#1
0
        /// <summary>
        /// Analyzes the cache miss for a specific pip.
        /// </summary>
        public static CacheMissAnalysisDetailAndResult AnalyzeCacheMiss(
            PipCacheMissInfo missInfo,
            Func <PipRecordingSession> oldSessionFunc,
            Func <PipRecordingSession> newSessionFunc,
            CacheMissDiffFormat diffFormat)
        {
            Contract.Requires(oldSessionFunc != null);
            Contract.Requires(newSessionFunc != null);

            var cacheMissType = missInfo.CacheMissType.ToString();
            var cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType);

            switch (missInfo.CacheMissType)
            {
            // Fingerprint miss.
            case PipCacheMissType.MissForDescriptorsDueToAugmentedWeakFingerprints:
            case PipCacheMissType.MissForDescriptorsDueToWeakFingerprints:
            case PipCacheMissType.MissForDescriptorsDueToStrongFingerprints:
                // Compute the pip unique output hash to use as the primary lookup key for fingerprint store entries
                cacheMissAnalysisDetailAndResult = AnalyzeFingerprints(oldSessionFunc, newSessionFunc, diffFormat, cacheMissType);
                break;

            // We had a weak and strong fingerprint match, but couldn't retrieve correct data from the cache
            case PipCacheMissType.MissForCacheEntry:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.DataMiss, "Cache entry missing from the cache.");
                break;

            case PipCacheMissType.MissForProcessMetadata:
            case PipCacheMissType.MissForProcessMetadataFromHistoricMetadata:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.DataMiss, "MetaData missing from the cache.");
                break;

            case PipCacheMissType.MissForProcessOutputContent:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.OutputMiss, "Outputs missing from the cache.", new JObject(new JProperty("MissingOutputs", missInfo.MissedOutputs)));
                break;

            case PipCacheMissType.MissDueToInvalidDescriptors:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.InvalidDescriptors, "Cache returned invalid data.");
                break;

            case PipCacheMissType.MissForDescriptorsDueToArtificialMissOptions:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.ArtificialMiss, "Cache miss artificially forced by user.");
                break;

            case PipCacheMissType.Hit:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.NoMiss, "Pip was a cache hit.");
                break;

            case PipCacheMissType.Invalid:
                cacheMissAnalysisDetailAndResult = new CacheMissAnalysisDetailAndResult(cacheMissType, CacheMissAnalysisResult.Invalid, "No valid changes or cache issues were detected to cause process execution, but a process still executed.");
                break;

            default:
                break;
            }

            return(cacheMissAnalysisDetailAndResult);
        }
示例#2
0
        /// <summary>
        /// Analyzes the cache miss for a specific pip.
        /// </summary>
        public static CacheMissAnalysisResult AnalyzeCacheMiss(
            TextWriter writer,
            PipCacheMissInfo missInfo,
            Func <PipRecordingSession> oldSessionFunc,
            Func <PipRecordingSession> newSessionFunc,
            CacheMissDiffFormat diffFormat)
        {
            Contract.Requires(oldSessionFunc != null);
            Contract.Requires(newSessionFunc != null);

            WriteLine($"Cache miss type: {missInfo.CacheMissType}", writer);
            WriteLine(string.Empty, writer);

            switch (missInfo.CacheMissType)
            {
            // Fingerprint miss
            case PipCacheMissType.MissForDescriptorsDueToWeakFingerprints:
            case PipCacheMissType.MissForDescriptorsDueToStrongFingerprints:
                // Compute the pip unique output hash to use as the primary lookup key for fingerprint store entries
                return(AnalyzeFingerprints(oldSessionFunc, newSessionFunc, writer, diffFormat));

            // We had a weak and strong fingerprint match, but couldn't retrieve correct data from the cache
            case PipCacheMissType.MissForCacheEntry:
                WriteLine($"Cache entry missing from the cache.", writer);
                return(CacheMissAnalysisResult.DataMiss);

            case PipCacheMissType.MissForProcessMetadata:
            case PipCacheMissType.MissForProcessMetadataFromHistoricMetadata:
                WriteLine($"MetaData missing from the cache.", writer);
                return(CacheMissAnalysisResult.DataMiss);

            case PipCacheMissType.MissForProcessOutputContent:
                WriteLine(new JProperty("MissingOutputs", missInfo.MissedOutputs).ToString(), writer);
                return(CacheMissAnalysisResult.OutputMiss);

            case PipCacheMissType.MissDueToInvalidDescriptors:
                WriteLine($"Cache returned invalid data.", writer);
                return(CacheMissAnalysisResult.InvalidDescriptors);

            case PipCacheMissType.MissForDescriptorsDueToArtificialMissOptions:
                WriteLine($"Cache miss artificially forced by user.", writer);
                return(CacheMissAnalysisResult.ArtificialMiss);

            case PipCacheMissType.Invalid:
                WriteLine($"Unexpected condition! No valid changes or cache issues were detected to cause process execution, but a process still executed.", writer);
                return(CacheMissAnalysisResult.Invalid);

            case PipCacheMissType.Hit:
                WriteLine($"Pip was a cache hit.", writer);
                return(CacheMissAnalysisResult.NoMiss);

            default:
                WriteLine($"Unexpected condition! Unknown cache miss type.", writer);
                return(CacheMissAnalysisResult.Invalid);
            }
        }
示例#3
0
        private void AnalyzePip(PipCacheMissInfo miss, Process pip, TextWriter writer)
        {
            string pipUniqueOutputHashStr = null;

            if ((pip as Process).TryComputePipUniqueOutputHash(PathTable, out var pipUniqueOutputHash, m_model.CachedGraph.MountPathExpander))
            {
                pipUniqueOutputHashStr = pipUniqueOutputHash.ToString();
            }

            WriteLine(pip.GetDescription(PipGraph.Context));

            var analysisResult = CacheMissAnalysisResult.Invalid;

            if (m_newCacheLookupReader != null &&
                miss.CacheMissType == PipCacheMissType.MissForDescriptorsDueToStrongFingerprints &&
                m_newCacheLookupReader.Store.ContainsFingerprintStoreEntry(pip.FormattedSemiStableHash, pipUniqueOutputHashStr))
            {
                // Strong fingerprint miss analysis is most accurate when compared to the fingerprints computed at cache lookup time
                // because those fingerprints capture the state of the disk at cache lookup time, including dynamic observations
                var resultAndDetail = CacheMissAnalysisUtilities.AnalyzeCacheMiss(
                    miss,
                    () => m_oldReader.StartPipRecordingSession(pip, pipUniqueOutputHashStr),
                    () => m_newCacheLookupReader.StartPipRecordingSession(pip, pipUniqueOutputHashStr),
                    CacheMissDiffFormat);
                analysisResult = resultAndDetail.Result;
                m_writer?.WriteLine(JsonConvert.SerializeObject(resultAndDetail.Detail));
            }
            else
            {
                var resultAndDetail = CacheMissAnalysisUtilities.AnalyzeCacheMiss(
                    miss,
                    () => m_oldReader.StartPipRecordingSession(pip, pipUniqueOutputHashStr),
                    () => m_newReader.StartPipRecordingSession(pip, pipUniqueOutputHashStr),
                    CacheMissDiffFormat);
                analysisResult = resultAndDetail.Result;
                m_writer?.WriteLine(JsonConvert.SerializeObject(resultAndDetail.Detail));
            }

            if (analysisResult == CacheMissAnalysisResult.MissingFromOldBuild)
            {
                Tracing.Logger.Log.FingerprintStorePipMissingFromOldBuild(LoggingContext);
            }
            else if (analysisResult == CacheMissAnalysisResult.MissingFromNewBuild)
            {
                Tracing.Logger.Log.FingerprintStorePipMissingFromNewBuild(LoggingContext);
            }
            else if (analysisResult == CacheMissAnalysisResult.UncacheablePip)
            {
                Tracing.Logger.Log.FingerprintStoreUncacheablePipAnalyzed(LoggingContext);
            }
        }
        private void AnalyzePip(PipCacheMissInfo miss, Process pip, TextWriter writer)
        {
            (pip as Process).TryComputePipUniqueOutputHash(PathTable, out var pipUniqueOutputHash, m_model.CachedGraph.MountPathExpander);
            WriteLine(pip.GetDescription(PipGraph.Context));

            var result = CacheMissAnalysisUtilities.AnalyzeCacheMiss(
                writer,
                miss,
                () => m_oldReader.StartPipRecordingSession(pip, pipUniqueOutputHash.ToString()),
                () => m_newReader.StartPipRecordingSession(pip, pipUniqueOutputHash.ToString()));

            if (result == CacheMissAnalysisResult.MissingFromOldBuild)
            {
                Tracing.Logger.Log.FingerprintStorePipMissingFromOldBuild(LoggingContext);
            }
            else if (result == CacheMissAnalysisResult.MissingFromNewBuild)
            {
                Tracing.Logger.Log.FingerprintStorePipMissingFromNewBuild(LoggingContext);
            }
            else if (result == CacheMissAnalysisResult.UncacheablePip)
            {
                Tracing.Logger.Log.FingerprintStoreUncacheablePipAnalyzed(LoggingContext);
            }
        }
示例#5
0
 internal void AddCacheMiss(PipCacheMissInfo cacheMissInfo)
 {
     m_pipCacheMissesDict.Add(cacheMissInfo.PipId, cacheMissInfo);
 }
        /// <summary>
        /// Analyzes cache misses.
        /// </summary>
        public override int Analyze()
        {
            Console.WriteLine("Starting fingerprint store analysis at: " + DateTime.Now.ToString());
            if (!m_newReader.TryGetCacheMissList(out var cacheMissList))
            {
                WriteLine("Could not retrieve cache miss list for analysis. There may have been a failure during the build.");
                return(0);
            }

            Console.WriteLine("Finished getting list of pips that had a cache miss at: " + DateTime.Now.ToString());

            if (m_oldReader.StoreVersion != m_newReader.StoreVersion)
            {
                WriteLine($"WARNING: Format version numbers of the fingerprint store do not match. Old: {m_oldReader.StoreVersion}, New: {m_newReader.StoreVersion}.");
            }

            if (SemiStableHashToRun != -1)
            {
                var firstMiss = cacheMissList.FirstOrDefault(x => PipTable.GetPipSemiStableHash(x.PipId) == SemiStableHashToRun);
                if (firstMiss.CacheMissType == PipCacheMissType.Invalid)
                {
                    foreach (var pipId in PipTable.StableKeys)
                    {
                        var possibleMatch = PipTable.GetPipSemiStableHash(pipId);
                        if (possibleMatch == SemiStableHashToRun)
                        {
                            firstMiss = new PipCacheMissInfo(pipId, PipCacheMissType.Hit);
                        }
                    }
                }

                Console.WriteLine("Analyzing single pip starting at: " + DateTime.Now.ToString());

                AnalyzePip(firstMiss, HydratePip(firstMiss.PipId), m_writer);
            }
            else
            {
                var frontierCacheMissList = new List <PipCacheMissInfo>();
                foreach (var miss in cacheMissList)
                {
                    if (m_model.HasChangedDependencies(miss.PipId) && !AllPips)
                    {
                        continue;
                    }

                    frontierCacheMissList.Add(miss);
                    m_model.MarkChanged(miss.PipId);
                }

                Console.WriteLine("Finding frontier pips done at " + DateTime.Now.ToString());
                int i = 0;
                foreach (var miss in frontierCacheMissList)
                {
                    if (i % 10 == 0)
                    {
                        Console.WriteLine("Done " + i + " of " + cacheMissList.Count);
                    }

                    var pip = HydratePip(miss.PipId);
                    WriteLine($"================== Analyzing pip ========================");

                    AnalyzePip(miss, pip, m_writer);
                    WriteLine("================== Complete pip ========================");
                    WriteLine();
                    i++;
                }
            }

            return(0);
        }
 /// <summary>
 /// Consider we may get multiple cache miss info for the same pip id when cache lookup fails/timeouts and it is retried
 /// </summary>
 internal void AddCacheMiss(PipCacheMissInfo cacheMissInfo) => m_pipCacheMissesDict[cacheMissInfo.PipId] = cacheMissInfo;