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)); }
/// <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); } }