Beispiel #1
0
        private RuntimeCacheMissAnalyzer(
            FingerprintStoreExecutionLogTarget logTarget,
            LoggingContext loggingContext,
            PipExecutionContext context,
            FingerprintStore previousFingerprintStore,
            IReadonlyDirectedGraph graph,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance,
            CacheMissDiffFormat cacheMissDiffFormat,
            bool cacheMissBatch,
            FingerprintStoreTestHooks testHooks = null)
        {
            m_loggingContext         = loggingContext;
            m_logTarget              = logTarget;
            m_context                = context;
            PreviousFingerprintStore = previousFingerprintStore;
            m_visitor                = new NodeVisitor(graph);
            m_changedPips            = new VisitationTracker(graph);
            m_pipCacheMissesDict     = new ConcurrentDictionary <PipId, PipCacheMissInfo>();
            m_runnablePipPerformance = runnablePipPerformance;
            m_cacheMissDiffFormat    = cacheMissDiffFormat;
            m_maxCacheMissCanPerform = cacheMissBatch ? EngineEnvironmentSettings.MaxNumPipsForCacheMissAnalysis.Value * EngineEnvironmentSettings.MaxMessagesPerBatch : EngineEnvironmentSettings.MaxNumPipsForCacheMissAnalysis.Value;

            m_batchLoggingQueue = cacheMissBatch ? NagleQueue <JProperty> .Create(
                BatchLogging,
                maxDegreeOfParallelism : 1,
                interval : TimeSpan.FromMinutes(1),
                batchSize : EngineEnvironmentSettings.MaxMessagesPerBatch) : null;


            m_testHooks = testHooks;
            m_testHooks?.InitRuntimeCacheMisses();
        }
        private RuntimeCacheMissAnalyzer(
            FingerprintStoreExecutionLogTarget logTarget,
            LoggingContext loggingContext,
            PipExecutionContext context,
            FingerprintStore previousFingerprintStore,
            IReadonlyDirectedGraph graph,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance,
            IConfiguration configuration,
            string downLoadedPreviousFingerprintStoreSavedPath,
            FingerprintStoreTestHooks testHooks = null)
        {
            m_loggingContext         = loggingContext;
            m_logTarget              = logTarget;
            m_context                = context;
            PreviousFingerprintStore = previousFingerprintStore;
            m_visitor                = new NodeVisitor(graph);
            m_changedPips            = new VisitationTracker(graph);
            m_pipCacheMissesDict     = new ConcurrentDictionary <PipId, PipCacheMissInfo>();
            m_runnablePipPerformance = runnablePipPerformance;

            m_batchLoggingQueue = configuration.Logging.CacheMissBatch ? NagleQueue <JProperty> .Create(
                BatchLogging,
                maxDegreeOfParallelism : 1,
                interval : TimeSpan.FromMinutes(5),
                batchSize : 100) : null;


            m_testHooks = testHooks;
            m_testHooks?.InitRuntimeCacheMisses();
            m_configuration = configuration;
            m_downLoadedPreviousFingerprintStoreSavedPath = downLoadedPreviousFingerprintStoreSavedPath;
        }
Beispiel #3
0
        public void FingerprintStoreSession(
            ScheduleRunResult result,
            Action <FingerprintStoreClass> storeOps,
            bool cacheLookupStore = false,
            bool readOnly         = true,
            FingerprintStoreTestHooks testHooks = null)
        {
            var storeDirectory = cacheLookupStore
                ? result.Config.Logging.CacheLookupFingerprintStoreLogDirectory.ToString(Context.PathTable)
                : result.Config.Layout.FingerprintStoreDirectory.ToString(Context.PathTable);

            using (var fingerprintStore = Open(storeDirectory, readOnly: readOnly, testHooks: testHooks).Result)
            {
                storeOps(fingerprintStore);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Creates a <see cref="FingerprintStoreExecutionLogTarget"/>.
        /// </summary>
        /// <returns>
        /// If successful, a <see cref="FingerprintStoreExecutionLogTarget"/> that logs to
        /// a <see cref="Tracing.FingerprintStore"/> at the provided directory;
        /// otherwise, null.
        /// </returns>
        public static FingerprintStoreExecutionLogTarget Create(
            PipExecutionContext context,
            PipTable pipTable,
            PipContentFingerprinter pipContentFingerprinter,
            string fingerprintStoreDirectory,
            LoggingContext loggingContext,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance = null,
            FingerprintStoreTestHooks testHooks = null)
        {
            var maxEntryAge   = new TimeSpan(hours: 0, minutes: configuration.Logging.FingerprintStoreMaxEntryAgeMinutes, seconds: 0);
            var possibleStore = FingerprintStore.Open(
                fingerprintStoreDirectory,
                maxEntryAge: maxEntryAge,
                mode: configuration.Logging.FingerprintStoreMode,
                loggingContext: loggingContext,
                testHooks: testHooks);

            if (possibleStore.Succeeded)
            {
                return(new FingerprintStoreExecutionLogTarget(
                           loggingContext,
                           context,
                           pipTable,
                           pipContentFingerprinter,
                           possibleStore.Result,
                           configuration,
                           cache,
                           graph,
                           runnablePipPerformance));
            }
            else
            {
                Logger.Log.FingerprintStoreUnableToOpen(loggingContext, possibleStore.Failure.DescribeIncludingInnerFailures());
            }

            return(null);
        }
        /// <summary>
        /// Creates a <see cref="FingerprintStoreExecutionLogTarget"/>.
        /// </summary>
        /// <returns>
        /// If successful, a <see cref="FingerprintStoreExecutionLogTarget"/> that logs to
        /// a <see cref="Tracing.FingerprintStore"/> at the provided directory;
        /// otherwise, null.
        /// </returns>
        public static FingerprintStoreExecutionLogTarget Create(
            PipExecutionContext context,
            PipTable pipTable,
            PipContentFingerprinter pipContentFingerprinter,
            LoggingContext loggingContext,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            CounterCollection <FingerprintStoreCounters> counters,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance = null,
            FingerprintStoreTestHooks testHooks = null)
        {
            var fingerprintStorePathString            = configuration.Layout.FingerprintStoreDirectory.ToString(context.PathTable);
            var cacheLookupFingerprintStorePathString = configuration.Logging.CacheLookupFingerprintStoreLogDirectory.ToString(context.PathTable);

            try
            {
                FileUtilities.CreateDirectoryWithRetry(fingerprintStorePathString);
            }
            catch (BuildXLException ex)
            {
                Logger.Log.FingerprintStoreUnableToCreateDirectory(loggingContext, fingerprintStorePathString, ex.Message);
                throw new BuildXLException("Unable to create fingerprint store directory: ", ex);
            }

            var maxEntryAge            = new TimeSpan(hours: 0, minutes: configuration.Logging.FingerprintStoreMaxEntryAgeMinutes, seconds: 0);
            var possibleExecutionStore = FingerprintStore.Open(
                fingerprintStorePathString,
                maxEntryAge: maxEntryAge,
                mode: configuration.Logging.FingerprintStoreMode,
                loggingContext: loggingContext,
                counters: counters,
                testHooks: testHooks);

            Possible <FingerprintStore> possibleCacheLookupStore = new Failure <string>("No attempt to create a cache lookup fingerprint store yet.");

            if (configuration.Logging.FingerprintStoreMode != FingerprintStoreMode.ExecutionFingerprintsOnly)
            {
                try
                {
                    FileUtilities.CreateDirectoryWithRetry(cacheLookupFingerprintStorePathString);
                }
                catch (BuildXLException ex)
                {
                    Logger.Log.FingerprintStoreUnableToCreateDirectory(loggingContext, fingerprintStorePathString, ex.Message);
                    throw new BuildXLException("Unable to create fingerprint store directory: ", ex);
                }

                possibleCacheLookupStore = FingerprintStore.Open(
                    cacheLookupFingerprintStorePathString,
                    maxEntryAge: maxEntryAge,
                    mode: configuration.Logging.FingerprintStoreMode,
                    loggingContext: loggingContext,
                    counters: counters,
                    testHooks: testHooks);
            }

            if (possibleExecutionStore.Succeeded &&
                (possibleCacheLookupStore.Succeeded || configuration.Logging.FingerprintStoreMode == FingerprintStoreMode.ExecutionFingerprintsOnly))
            {
                return(new FingerprintStoreExecutionLogTarget(
                           loggingContext,
                           context,
                           pipTable,
                           pipContentFingerprinter,
                           possibleExecutionStore.Result,
                           possibleCacheLookupStore.Succeeded ? possibleCacheLookupStore.Result : null,
                           configuration,
                           cache,
                           graph,
                           counters,
                           runnablePipPerformance));
            }
            else
            {
                if (!possibleExecutionStore.Succeeded)
                {
                    Logger.Log.FingerprintStoreUnableToOpen(loggingContext, possibleExecutionStore.Failure.DescribeIncludingInnerFailures());
                }

                if (!possibleCacheLookupStore.Succeeded)
                {
                    Logger.Log.FingerprintStoreUnableToOpen(loggingContext, possibleCacheLookupStore.Failure.DescribeIncludingInnerFailures());
                }
            }

            return(null);
        }
Beispiel #6
0
 /// <summary>
 /// Encapsulates one "session" with a fingerprint store.
 /// </summary>
 /// <param name="storeDirectory">
 /// Directory of the fingerprint store.
 /// </param>
 /// <param name="storeOps">
 /// The store operations to execute.
 /// </param>
 public static CounterCollection <FingerprintStoreCounters> FingerprintStoreSession(string storeDirectory, Action <FingerprintStore> storeOps, bool readOnly = true, FingerprintStoreTestHooks testHooks = null)
 {
     using (var fingerprintStore = FingerprintStore.Open(storeDirectory, readOnly: readOnly, testHooks: testHooks).Result)
     {
         storeOps(fingerprintStore);
         return(fingerprintStore.Counters);
     }
 }
Beispiel #7
0
        /// <summary>
        /// Initiates the task to load the fingerprint store that will be used for cache miss analysis
        /// </summary>
        public static async Task <RuntimeCacheMissAnalyzer> TryCreateAsync(
            FingerprintStoreExecutionLogTarget logTarget,
            LoggingContext loggingContext,
            PipExecutionContext context,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance,
            FingerprintStoreTestHooks testHooks = null)
        {
            using (logTarget.Counters.StartStopwatch(FingerprintStoreCounters.InitializeCacheMissAnalysisDuration))
            {
                var option = configuration.Logging.CacheMissAnalysisOption;
                if (option.Mode == CacheMissMode.Disabled)
                {
                    return(null);
                }

                Possible <FingerprintStore> possibleStore;

                if (option.Mode == CacheMissMode.Local)
                {
                    possibleStore = FingerprintStore.CreateSnapshot(logTarget.ExecutionFingerprintStore, loggingContext);
                }
                else
                {
                    string path = null;
                    if (option.Mode == CacheMissMode.CustomPath)
                    {
                        path = option.CustomPath.ToString(context.PathTable);
                    }
                    else
                    {
                        Contract.Assert(option.Mode == CacheMissMode.Remote);
                        foreach (var key in option.Keys)
                        {
                            var cacheSavePath = configuration.Logging.FingerprintsLogDirectory
                                                .Combine(context.PathTable, Scheduler.FingerprintStoreDirectory + "." + key);
#pragma warning disable AsyncFixer02 // This should explicitly happen synchronously since it interacts with the PathTable and StringTable
                            var result = cache.TryRetrieveFingerprintStoreAsync(loggingContext, cacheSavePath, context.PathTable, key, configuration.Schedule.EnvironmentFingerprint).Result;
#pragma warning restore AsyncFixer02
                            if (result.Succeeded && result.Result)
                            {
                                path = cacheSavePath.ToString(context.PathTable);
                                break;
                            }
                        }

                        if (string.IsNullOrEmpty(path))
                        {
                            Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Could not find the fingerprint store for any given key: {string.Join(",", option.Keys)}"));
                            return(null);
                        }
                    }

                    // Unblock caller
                    // WARNING: The rest can simultenously happen with saving the graph files to disk.
                    // We should not create any paths or strings by using PathTable and StringTable.
                    await Task.Yield();

                    possibleStore = FingerprintStore.Open(path, readOnly: true);
                }

                if (possibleStore.Succeeded)
                {
                    Logger.Log.SuccessLoadFingerprintStoreToCompare(loggingContext, option.Mode.ToString(), possibleStore.Result.StoreDirectory);
                    return(new RuntimeCacheMissAnalyzer(
                               logTarget,
                               loggingContext,
                               context,
                               possibleStore.Result,
                               graph,
                               runnablePipPerformance,
                               configuration.Logging.CacheMissDiffFormat,
                               configuration.Logging.CacheMissBatch,
                               testHooks: testHooks));
                }

                Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Failed to read the fingerprint store to compare. Mode: {option.Mode.ToString()} Failure: {possibleStore.Failure.DescribeIncludingInnerFailures()}"));
                return(null);
            }
        }
        /// <summary>
        /// Initiates the task to load the fingerprint store that will be used for cache miss analysis
        /// </summary>
        public static async Task <RuntimeCacheMissAnalyzer> TryCreateAsync(
            FingerprintStoreExecutionLogTarget logTarget,
            LoggingContext loggingContext,
            PipExecutionContext context,
            IConfiguration configuration,
            EngineCache cache,
            IReadonlyDirectedGraph graph,
            IDictionary <PipId, RunnablePipPerformanceInfo> runnablePipPerformance,
            FingerprintStoreTestHooks testHooks = null)
        {
            // Unblock caller
            await Task.Yield();

            using (logTarget.Counters.StartStopwatch(FingerprintStoreCounters.InitializeCacheMissAnalysisDuration))
            {
                var    option = configuration.Logging.CacheMissAnalysisOption;
                string downLoadedPriviousFingerprintStoreSavedPath = null;
                if (option.Mode == CacheMissMode.Disabled)
                {
                    return(null);
                }

                Possible <FingerprintStore> possibleStore;

                PathTable newPathTable = new PathTable();
                if (option.Mode == CacheMissMode.Local)
                {
                    possibleStore = FingerprintStore.CreateSnapshot(logTarget.ExecutionFingerprintStore, loggingContext);
                }
                else
                {
                    string path = null;
                    if (option.Mode == CacheMissMode.CustomPath)
                    {
                        path = option.CustomPath.ToString(context.PathTable);
                    }
                    else
                    {
                        Contract.Assert(option.Mode == CacheMissMode.Remote);
                        foreach (var key in option.Keys)
                        {
                            var fingerprintsLogDirectoryStr = configuration.Logging.FingerprintsLogDirectory.ToString(context.PathTable);
                            var fingerprintsLogDirectory    = AbsolutePath.Create(newPathTable, fingerprintsLogDirectoryStr);

                            var cacheSavePath = fingerprintsLogDirectory.Combine(newPathTable, Scheduler.FingerprintStoreDirectory + "." + key);
                            var result        = await cache.TryRetrieveFingerprintStoreAsync(loggingContext, cacheSavePath, newPathTable, key, configuration, context.CancellationToken);

                            if (result.Succeeded && result.Result)
                            {
                                path = cacheSavePath.ToString(newPathTable);
                                downLoadedPriviousFingerprintStoreSavedPath = path;
                                break;
                            }
                        }

                        if (string.IsNullOrEmpty(path))
                        {
                            Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Could not find the fingerprint store for any given key: {string.Join(",", option.Keys)}"));
                            return(null);
                        }
                    }

                    possibleStore = FingerprintStore.Open(path, readOnly: true);
                }

                if (possibleStore.Succeeded)
                {
                    Logger.Log.SuccessLoadFingerprintStoreToCompare(loggingContext, option.Mode.ToString(), possibleStore.Result.StoreDirectory);
                    return(new RuntimeCacheMissAnalyzer(
                               logTarget,
                               loggingContext,
                               context,
                               possibleStore.Result,
                               graph,
                               runnablePipPerformance,
                               configuration,
                               downLoadedPriviousFingerprintStoreSavedPath,
                               testHooks: testHooks));
                }

                Logger.Log.GettingFingerprintStoreTrace(loggingContext, I($"Failed to read the fingerprint store to compare. Mode: {option.Mode.ToString()} Failure: {possibleStore.Failure.DescribeIncludingInnerFailures()}"));
                return(null);
            }
        }