Пример #1
0
        private GraphReuseResult ReloadPipGraphOnly(
            EngineSerializer serializer,
            LoggingContext loggingContext,
            EngineState engineState,
            InputTracker.InputChanges inputChanges)
        {
            Tuple <PipGraph, EngineContext> t = null;

            try
            {
                t = EngineSchedule.LoadPipGraphAsync(
                    Context,
                    serializer,
                    Configuration,
                    loggingContext,
                    engineState).GetAwaiter().GetResult();
            }
            catch (BuildXLException e)
            {
                Logger.Log.FailedReloadPipGraph(loggingContext, e.ToString());
            }

            if (t == null)
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            var newContext = t.Item2;

            if (!ShouldReuseReloadedEngineContextGivenHistoricData(loggingContext, newContext.NextHistoricTableSizes))
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            var newPathTable = newContext.PathTable;
            var pathRemapper = new PathRemapper(Context.PathTable, newPathTable);

            Configuration = new ConfigurationImpl(Configuration, pathRemapper);

            m_initialCommandLineConfiguration = new CommandLineConfiguration(m_initialCommandLineConfiguration, pathRemapper);

            // Invalidate the old context to ensure nothing uses it anymore
            // Update engine state to deserialized state
            Context.Invalidate();
            Context = newContext;

            // Additionally recreate front end controller, because the old one uses the invalidated context.
            //   - to fully initialize the front end, we have to go through all the steps that have already been
            //     executed on the old controller; those steps are (1) InitializeHost, and (2) ParseConfig
            FrontEndController = m_frontEndControllerFactory.Create(Context.PathTable, Context.SymbolTable);
            FrontEndController.InitializeHost(Context.ToFrontEndContext(loggingContext), m_initialCommandLineConfiguration);

            var configurationEngine = new BasicFrontEndEngineAbstraction(Context.PathTable, Context.FileSystem, m_initialCommandLineConfiguration);

            if (!configurationEngine.TryPopulateWithDefaultMountsTable(loggingContext, Context, m_initialCommandLineConfiguration, m_initialCommandLineConfiguration.Startup.Properties))
            {
                Contract.Assert(loggingContext.ErrorWasLogged);
                return(null);
            }

            FrontEndController.ParseConfig(configurationEngine, m_initialCommandLineConfiguration);

            return(GraphReuseResult.CreateForPartialReuse(t.Item1, inputChanges));
        }
Пример #2
0
        /// <summary>
        /// Attempt to reuse the pip graph from a previous run
        /// </summary>
        private GraphReuseResult AttemptToReuseGraph(
            LoggingContext outerLoggingContext,
            int maxDegreeOfParallelism,
            GraphFingerprint graphFingerprint,
            IReadOnlyDictionary <string, string> properties,
            CacheInitializationTask cacheInitializationTask,
            JournalState journalState,
            EngineState engineState)
        {
            GraphCacheCheckStatistics cacheGraphStats = CheckGraphCacheReuse(
                outerLoggingContext,
                maxDegreeOfParallelism,
                graphFingerprint,
                properties,
                cacheInitializationTask,
                journalState,
                out var serializer,
                out var inputChanges);

            // There are 3 cases in which we should reload the graph
            //   - we have a graph cache hit
            //   - the build is configured to reload the graph no matter what
            //   - graph patching is enabled and the reason for cache miss was 'SpecFileChanges'
            var shouldReload =
                cacheGraphStats.WasHit ||
                Configuration.Cache.CachedGraphPathToLoad.IsValid ||
                PartialReloadCondition(Configuration.FrontEnd, cacheGraphStats);

            if (!shouldReload)
            {
                return(GraphReuseResult.CreateForNoReuse(inputChanges));
            }

            bool fullReload = !PartialReloadCondition(Configuration.FrontEnd, cacheGraphStats);

            // Now we actually reload the graph
            var reloadStats = default(GraphCacheReloadStatistics);

            using (var tb = TimedBlock <EmptyStruct, GraphCacheReloadStatistics> .Start(
                       outerLoggingContext,
                       Statistics.GraphCacheReload,
                       (context, emptyStruct) =>
            {
                if (fullReload)
                {
                    Logger.Log.ReloadingPipGraphStart(context);
                }
                else
                {
                    Logger.Log.PartiallyReloadingEngineState(context);
                }
            },
                       default(EmptyStruct),
                       (context, graphCacheCheckStatistics) =>
            {
                Logger.Log.PartiallyReloadingEngineStateComplete(context, graphCacheCheckStatistics);
                m_enginePerformanceInfo.GraphReloadDurationMs = graphCacheCheckStatistics.ElapsedMilliseconds;
            },
                       () => reloadStats))
            {
                var reuseResult = fullReload
                    ? ReloadEngineSchedule(
                    serializer,
                    cacheInitializationTask,
                    journalState,
                    tb.LoggingContext,
                    engineState,
                    inputChanges,
                    graphFingerprint?.ExactFingerprint.BuildEngineHash.ToString())
                    : ReloadPipGraphOnly(serializer, tb.LoggingContext, engineState, inputChanges);

                // Set telemetry statistics
                reloadStats.SerializedFileSizeBytes = serializer.BytesDeserialized;
                reloadStats.Success = !reuseResult.IsNoReuse;

                return(reuseResult);
            }
        }