提交 d7ca4eb2 编写于 作者: H Heejae Chang

implements IProjectCacheHostService in OOP.

workspace will cache everything in memory if this service doesn't exist in workspace. now this being exist, workspace will start to put things such as text, tree, compilation either kick out from memory or save it to temporary storage.

this should reduce memory foot print once things become idle, but this doesn't help memory footprint while feature is running.

with this service, once OOP become idle, memory foot print goes down to about 700MB to 1 GB. but still while code lens run, memory goes up to 3GB.
上级 1327b455
......@@ -623,8 +623,6 @@
<Compile Include="Implementation\Workspaces\EditorErrorReportingServiceFactory.cs" />
<Compile Include="Implementation\Workspaces\ProjectCacheServiceFactory.cs" />
<Compile Include="Implementation\Workspaces\EditorTextFactoryService.cs" />
<Compile Include="Implementation\Workspaces\ProjectCacheService.cs" />
<Compile Include="Implementation\Workspaces\ProjectCacheService.SimpleMRUCache.cs" />
<Compile Include="Implementation\Workspaces\TextUndoHistoryWorkspaceServiceFactoryService.cs" />
<Compile Include="Implementation\Workspaces\WorkspaceTaskSchedulerFactoryFactory.cs" />
<Compile Include="IRefactorNotifyService.cs" />
......
......@@ -14,6 +14,11 @@ internal partial class ProjectCacheHostServiceFactory : IWorkspaceServiceFactory
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
if (workspaceServices.Workspace.Kind != WorkspaceKind.Host)
{
return new ProjectCacheService(workspaceServices.Workspace);
}
var service = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);
// Also clear the cache when the solution is cleared or removed.
......
......@@ -58,6 +58,7 @@
<InternalsVisibleTo Include="MonoDevelop.Refactoring" />
<InternalsVisibleTo Include="MonoDevelop.CSharpBinding" />
<InternalsVisibleTo Include="MonoDevelop.VBNetBinding" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Remote.Workspaces" />
<InternalsVisibleToTest Include="Roslyn.DebuggerVisualizers" />
<InternalsVisibleTo Include="Roslyn.Hosting.Diagnostics" />
<InternalsVisibleToTest Include="Roslyn.InteractiveHost.UnitTests" />
......@@ -681,6 +682,8 @@
<Compile Include="UseObjectInitializer\AbstractUseObjectInitializerCodeFixProvider.cs" />
<Compile Include="Workspace\BackgroundCompiler.cs" />
<Compile Include="Workspace\BackgroundParser.cs" />
<Compile Include="Workspace\ProjectCacheService.cs" />
<Compile Include="Workspace\ProjectCacheService.SimpleMRUCache.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="FeaturesResources.resx">
......
......@@ -3,12 +3,11 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Workspaces
namespace Microsoft.CodeAnalysis.Host
{
internal partial class ProjectCacheService : IProjectCacheHostService
{
......
......@@ -6,7 +6,7 @@
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Workspaces
namespace Microsoft.CodeAnalysis.Host
{
/// <summary>
/// This service will implicitly cache previous Compilations used by each supported Workspace implementation.
......@@ -27,18 +27,18 @@ internal partial class ProjectCacheService : IProjectCacheHostService
private readonly SimpleMRUCache _implicitCache;
private readonly ImplicitCacheMonitor _implicitCacheMonitor;
public ProjectCacheService(Workspace workspace)
{
_workspace = workspace;
}
public ProjectCacheService(Workspace workspace, int implicitCacheTimeout)
{
_workspace = workspace;
// Only create implicit cache for Visual Studio Workspace (the cost of the
// cache likely outweighs the benefit for the other types of Workspaces).
if (workspace?.Kind == WorkspaceKind.Host)
{
_implicitCache = new SimpleMRUCache();
_implicitCacheMonitor = new ImplicitCacheMonitor(this, implicitCacheTimeout);
}
_implicitCache = new SimpleMRUCache();
_implicitCacheMonitor = new ImplicitCacheMonitor(this, implicitCacheTimeout);
}
public bool IsImplicitCacheEmpty
......
......@@ -27,6 +27,11 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
private static IWorkspaceService GetMiscProjectCache(HostWorkspaceServices workspaceServices)
{
if (workspaceServices.Workspace.Kind != WorkspaceKind.Host)
{
return new ProjectCacheService(workspaceServices.Workspace);
}
var projectCacheService = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);
// Also clear the cache when the solution is cleared or removed.
......
......@@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.Telemetry;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Workspaces.Diagnostics;
using Roslyn.Utilities;
......@@ -39,6 +40,20 @@ public DiagnosticComputer(Project project)
return DiagnosticAnalysisResultMap.Create(ImmutableDictionary<string, DiagnosticAnalysisResultBuilder>.Empty, ImmutableDictionary<string, AnalyzerTelemetryInfo>.Empty);
}
var cacheService = _project.Solution.Workspace.Services.GetService<IProjectCacheService>();
using (var cache = cacheService.EnableCaching(_project.Id))
{
return await AnalyzeAsync(analyzerMap, analyzers, reportSuppressedDiagnostics, logAnalyzerExecutionTime, cancellationToken).ConfigureAwait(false);
}
}
private async Task<DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder>> AnalyzeAsync(
BidirectionalMap<string, DiagnosticAnalyzer> analyzerMap,
ImmutableArray<DiagnosticAnalyzer> analyzers,
bool reportSuppressedDiagnostics,
bool logAnalyzerExecutionTime,
CancellationToken cancellationToken)
{
var compilation = await _project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
// TODO: can we support analyzerExceptionFilter in remote host?
......@@ -70,9 +85,10 @@ public DiagnosticComputer(Project project)
var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken);
return DiagnosticAnalysisResultMap.Create(builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
analysisResult.AnalyzerTelemetryInfo.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
_exceptions.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value.ToImmutableArray()));
return DiagnosticAnalysisResultMap.Create(
builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
analysisResult.AnalyzerTelemetryInfo.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
_exceptions.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value.ToImmutableArray()));
}
private void OnAnalyzerException(Exception exception, DiagnosticAnalyzer analyzer, Diagnostic diagnostic)
......
......@@ -68,7 +68,9 @@
<Compile Include="Services\AssetSource.cs" />
<Compile Include="Services\AssetService.cs" />
<Compile Include="Services\AssetStorage.cs" />
<Compile Include="Services\ChecksumSourceText.cs" />
<Compile Include="Services\CompilationService.cs" />
<Compile Include="Services\ProjectCacheHostServiceFactory.cs" />
<Compile Include="Services\RoslynServices.cs" />
<Compile Include="Services\SolutionService.cs" />
<Compile Include="Storage\RemotePersistentStorageLocationService.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Remote
{
/// <summary>
/// source text that has checksum tied to it
/// </summary>
internal class ChecksumSourceText : SourceText
{
private readonly SourceText _sourceText;
public ChecksumSourceText(Checksum checksum, SourceText sourceText)
{
Checksum = checksum;
_sourceText = sourceText;
}
public Checksum Checksum { get; }
public override char this[int position] => _sourceText[position];
public override Encoding Encoding => _sourceText.Encoding;
public override int Length => _sourceText.Length;
public override SourceTextContainer Container => _sourceText.Container;
public override SourceText WithChanges(IEnumerable<TextChange> changes) => _sourceText.WithChanges(changes);
public override SourceText GetSubText(TextSpan span) => _sourceText.GetSubText(span);
public override IReadOnlyList<TextChange> GetTextChanges(SourceText oldText) => _sourceText.GetTextChanges(oldText);
public override IReadOnlyList<TextChangeRange> GetChangeRanges(SourceText oldText) => _sourceText.GetChangeRanges(oldText);
public override void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) =>
_sourceText.CopyTo(sourceIndex, destination, destinationIndex, count);
public override void Write(TextWriter writer, TextSpan span, CancellationToken cancellationToken = default(CancellationToken)) =>
_sourceText.Write(writer, span, cancellationToken);
public override bool Equals(object obj) => _sourceText.Equals(obj);
public override int GetHashCode() => _sourceText.GetHashCode();
public override string ToString() => _sourceText.ToString();
public override string ToString(TextSpan span) => _sourceText.ToString(span);
protected override TextLineCollection GetLinesCore() => _sourceText.Lines;
protected override bool ContentEqualsImpl(SourceText other)
{
var otherChecksum = other as ChecksumSourceText;
if (otherChecksum != null)
{
return Checksum == otherChecksum.Checksum;
}
return _sourceText.ContentEquals(other);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Composition;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
namespace Microsoft.CodeAnalysis.Remote
{
[ExportWorkspaceServiceFactory(typeof(IProjectCacheHostService), ServiceLayer.Host)]
[Shared]
internal partial class ProjectCacheHostServiceFactory : IWorkspaceServiceFactory
{
private const int ImplicitCacheTimeoutInMS = 10000;
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);
}
}
}
......@@ -102,7 +102,9 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
var textLoader = TextLoader.From(
TextAndVersion.Create(
await _assetService.GetAssetAsync<SourceText>(documentSnapshot.Text, cancellationToken).ConfigureAwait(false),
new ChecksumSourceText(
documentSnapshot.Text,
await _assetService.GetAssetAsync<SourceText>(documentSnapshot.Text, cancellationToken).ConfigureAwait(false)),
VersionStamp.Create(),
documentInfo.FilePath));
......@@ -155,7 +157,9 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
var textLoader = TextLoader.From(
TextAndVersion.Create(
await _assetService.GetAssetAsync<SourceText>(documentSnapshot.Text, cancellationToken).ConfigureAwait(false),
new ChecksumSourceText(
documentSnapshot.Text,
await _assetService.GetAssetAsync<SourceText>(documentSnapshot.Text, cancellationToken).ConfigureAwait(false)),
VersionStamp.Create(),
documentInfo.FilePath));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册