/// <summary> /// Creates the engine context /// </summary> internal EngineContext( CancellationToken cancellationToken, PathTable pathTable, SymbolTable symbolTable, QualifierTable qualifierTable, IFileSystem fileSystem, TokenTextTable tokenTextTable, CounterCollection <EngineCounter> engineCounters = null, HistoricTableSizes historicTableSizes = null) : base(cancellationToken, pathTable.StringTable, pathTable, symbolTable, qualifierTable, tokenTextTable) { Contract.Requires(pathTable != null); Contract.Requires(symbolTable != null); Contract.Requires(fileSystem != null); Contract.Requires(tokenTextTable != null); Contract.Requires(pathTable.StringTable == symbolTable.StringTable); Contract.Requires(pathTable.StringTable == qualifierTable.StringTable); PipDataBuilderPool = new ObjectPool <PipDataBuilder>(() => new PipDataBuilder(StringTable), builder => builder.Clear()); EngineCounters = engineCounters ?? new CounterCollection <EngineCounter>(); FileSystem = fileSystem; var historicData = (IReadOnlyList <HistoricDataPoint>)historicTableSizes ?? CollectionUtilities.EmptyArray <HistoricDataPoint>(); HistoricTableSizes = new HistoricTableSizes(historicData); }
private EngineState( Guid graphId, StringTable stringTable, PathTable pathTable, SymbolTable symbolTable, QualifierTable qualifierTable, PipTable pipTable, PipGraph pipGraph, MountPathExpander mountPathExpander, SchedulerState schedulerState, HistoricTableSizes historicTableSizes, FileContentTable fileContentTable) { Contract.Requires(graphId != default(Guid), "GraphId is not unique enough to be represented in EngineState"); Contract.Requires(stringTable != null); Contract.Requires(pathTable != null); Contract.Requires(symbolTable != null); Contract.Requires(qualifierTable != null); Contract.Requires(stringTable == pathTable.StringTable); Contract.Requires(pathTable.StringTable == symbolTable.StringTable); Contract.Requires(pathTable.StringTable == qualifierTable.StringTable); Contract.Requires(pipTable != null); Contract.Requires(!pipTable.IsDisposed); Contract.Requires(pipGraph != null); Contract.Requires(mountPathExpander != null); Contract.Requires(schedulerState != null); Contract.Requires(historicTableSizes != null); Contract.Requires(fileContentTable != null); m_stringTable = stringTable; m_pathTable = pathTable; m_symbolTable = symbolTable; m_qualifierTable = qualifierTable; m_pipTable = pipTable; m_pipGraph = pipGraph; m_mountPathExpander = mountPathExpander; m_schedulerState = schedulerState; m_graphId = graphId; m_historicTableSizes = historicTableSizes; m_fileContentTable = fileContentTable; }
private CachedGraphLoader(CancellationToken cancellationToken, EngineSerializer serializer) { Serializer = serializer; m_pipGraphIdTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.PipGraph, async reader => { var graphId = await PipGraph.DeserializeGraphIdAsync(reader); return(graphId.Item1); }); var directedGraphTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.DirectedGraph, DeserializedDirectedGraph.DeserializeAsync); m_stringTableTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.StringTable, StringTable.DeserializeAsync); m_pathTableTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.PathTable, reader => reader.ReadPathTableAsync(m_stringTableTask.Value)); m_symbolTableTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.SymbolTable, reader => reader.ReadSymbolTableAsync(m_stringTableTask.Value)); m_qualifierTableTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.QualifierTable, reader => reader.ReadQualifierTableAsync(m_stringTableTask.Value)); m_pipTableTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.PipTable, (reader) => PipTable.DeserializeAsync( reader, m_pathTableTask.Value, m_symbolTableTask.Value, EngineSchedule.PipTableInitialBufferSize, EngineSchedule.PipTableMaxDegreeOfParallelismDuringConstruction, debug: false)); m_mountPathExpanderTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.MountPathExpander, reader => MountPathExpander.DeserializeAsync(reader, m_pathTableTask.Value)); m_pipExecutionContextTask = CreateAsyncLazy(() => Task.Run( async() => { var stringTable = await m_stringTableTask.Value; var pathTable = await m_pathTableTask.Value; var symbolTable = await m_symbolTableTask.Value; var qualifierTable = await m_qualifierTableTask.Value; if (stringTable != null && pathTable != null && symbolTable != null && qualifierTable != null) { return((PipExecutionContext) new SchedulerContext(cancellationToken, stringTable, pathTable, symbolTable, qualifierTable)); } return(null); })); m_historicDataTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.HistoricTableSizes, reader => Task.FromResult(HistoricTableSizes.Deserialize(reader))); m_pipGraphTask = CreateLazyFileDeserialization( serializer, GraphCacheFile.PipGraph, reader => PipGraph.DeserializeAsync( reader, serializer.LoggingContext, m_pipTableTask.Value, directedGraphTask.Value, m_pipExecutionContextTask.Value, ToSemanticPathExpander(m_mountPathExpanderTask.Value))); m_cachedGraphTask = CreateAsyncLazy(() => CreateCachedGraph(m_pipTableTask.Value, m_pipGraphTask.Value, directedGraphTask.Value, m_pipExecutionContextTask.Value, m_mountPathExpanderTask.Value)); }
private static bool ShouldReuseReloadedEngineContextGivenHistoricData(LoggingContext loggingContext, HistoricTableSizes historicTableSizes) { Contract.Requires(historicTableSizes != null); Contract.Requires(historicTableSizes.Count > 0); var gen = historicTableSizes.Count; // no historic data --> reuse if (gen == 1) { Logger.Log.EngineContextHeuristicOutcomeReuse(loggingContext, gen, "first generation context is always reused"); return(true); } var leastRecentStats = historicTableSizes[0]; var mostRecentStats = historicTableSizes[historicTableSizes.Count - 1]; var leastRecentTotalSizeInBytes = leastRecentStats.TotalSizeInBytes(); var mostRecentTotalsizeInBytes = mostRecentStats.TotalSizeInBytes(); // if the total size of all tables has more than doubled --> don't reuse if (mostRecentTotalsizeInBytes > leastRecentTotalSizeInBytes * 2) { Logger.Log.EngineContextHeuristicOutcomeSkip( loggingContext, gen, I($"total size has more than doubled (oldest size = {leastRecentTotalSizeInBytes} bytes, newest size = {mostRecentTotalsizeInBytes} bytes)")); return(false); } Logger.Log.EngineContextHeuristicOutcomeReuse( loggingContext, gen, I($"total size hasn't grown too much (oldest size = {leastRecentTotalSizeInBytes} bytes, newest size = {mostRecentTotalsizeInBytes} bytes)")); return(true); }