提交 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 @@ ...@@ -623,8 +623,6 @@
<Compile Include="Implementation\Workspaces\EditorErrorReportingServiceFactory.cs" /> <Compile Include="Implementation\Workspaces\EditorErrorReportingServiceFactory.cs" />
<Compile Include="Implementation\Workspaces\ProjectCacheServiceFactory.cs" /> <Compile Include="Implementation\Workspaces\ProjectCacheServiceFactory.cs" />
<Compile Include="Implementation\Workspaces\EditorTextFactoryService.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\TextUndoHistoryWorkspaceServiceFactoryService.cs" />
<Compile Include="Implementation\Workspaces\WorkspaceTaskSchedulerFactoryFactory.cs" /> <Compile Include="Implementation\Workspaces\WorkspaceTaskSchedulerFactoryFactory.cs" />
<Compile Include="IRefactorNotifyService.cs" /> <Compile Include="IRefactorNotifyService.cs" />
......
...@@ -14,6 +14,11 @@ internal partial class ProjectCacheHostServiceFactory : IWorkspaceServiceFactory ...@@ -14,6 +14,11 @@ internal partial class ProjectCacheHostServiceFactory : IWorkspaceServiceFactory
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{ {
if (workspaceServices.Workspace.Kind != WorkspaceKind.Host)
{
return new ProjectCacheService(workspaceServices.Workspace);
}
var service = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS); var service = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);
// Also clear the cache when the solution is cleared or removed. // Also clear the cache when the solution is cleared or removed.
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
<InternalsVisibleTo Include="MonoDevelop.Refactoring" /> <InternalsVisibleTo Include="MonoDevelop.Refactoring" />
<InternalsVisibleTo Include="MonoDevelop.CSharpBinding" /> <InternalsVisibleTo Include="MonoDevelop.CSharpBinding" />
<InternalsVisibleTo Include="MonoDevelop.VBNetBinding" /> <InternalsVisibleTo Include="MonoDevelop.VBNetBinding" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Remote.Workspaces" />
<InternalsVisibleToTest Include="Roslyn.DebuggerVisualizers" /> <InternalsVisibleToTest Include="Roslyn.DebuggerVisualizers" />
<InternalsVisibleTo Include="Roslyn.Hosting.Diagnostics" /> <InternalsVisibleTo Include="Roslyn.Hosting.Diagnostics" />
<InternalsVisibleToTest Include="Roslyn.InteractiveHost.UnitTests" /> <InternalsVisibleToTest Include="Roslyn.InteractiveHost.UnitTests" />
...@@ -681,6 +682,8 @@ ...@@ -681,6 +682,8 @@
<Compile Include="UseObjectInitializer\AbstractUseObjectInitializerCodeFixProvider.cs" /> <Compile Include="UseObjectInitializer\AbstractUseObjectInitializerCodeFixProvider.cs" />
<Compile Include="Workspace\BackgroundCompiler.cs" /> <Compile Include="Workspace\BackgroundCompiler.cs" />
<Compile Include="Workspace\BackgroundParser.cs" /> <Compile Include="Workspace\BackgroundParser.cs" />
<Compile Include="Workspace\ProjectCacheService.cs" />
<Compile Include="Workspace\ProjectCacheService.SimpleMRUCache.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="FeaturesResources.resx"> <EmbeddedResource Include="FeaturesResources.resx">
......
...@@ -3,12 +3,11 @@ ...@@ -3,12 +3,11 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.SolutionCrawler;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Workspaces namespace Microsoft.CodeAnalysis.Host
{ {
internal partial class ProjectCacheService : IProjectCacheHostService internal partial class ProjectCacheService : IProjectCacheHostService
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Workspaces namespace Microsoft.CodeAnalysis.Host
{ {
/// <summary> /// <summary>
/// This service will implicitly cache previous Compilations used by each supported Workspace implementation. /// This service will implicitly cache previous Compilations used by each supported Workspace implementation.
...@@ -27,18 +27,18 @@ internal partial class ProjectCacheService : IProjectCacheHostService ...@@ -27,18 +27,18 @@ internal partial class ProjectCacheService : IProjectCacheHostService
private readonly SimpleMRUCache _implicitCache; private readonly SimpleMRUCache _implicitCache;
private readonly ImplicitCacheMonitor _implicitCacheMonitor; private readonly ImplicitCacheMonitor _implicitCacheMonitor;
public ProjectCacheService(Workspace workspace)
{
_workspace = workspace;
}
public ProjectCacheService(Workspace workspace, int implicitCacheTimeout) public ProjectCacheService(Workspace workspace, int implicitCacheTimeout)
{ {
_workspace = workspace; _workspace = workspace;
// Only create implicit cache for Visual Studio Workspace (the cost of the _implicitCache = new SimpleMRUCache();
// cache likely outweighs the benefit for the other types of Workspaces). _implicitCacheMonitor = new ImplicitCacheMonitor(this, implicitCacheTimeout);
if (workspace?.Kind == WorkspaceKind.Host)
{
_implicitCache = new SimpleMRUCache();
_implicitCacheMonitor = new ImplicitCacheMonitor(this, implicitCacheTimeout);
}
} }
public bool IsImplicitCacheEmpty public bool IsImplicitCacheEmpty
......
...@@ -27,6 +27,11 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) ...@@ -27,6 +27,11 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
private static IWorkspaceService GetMiscProjectCache(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); var projectCacheService = new ProjectCacheService(workspaceServices.Workspace, ImplicitCacheTimeoutInMS);
// Also clear the cache when the solution is cleared or removed. // Also clear the cache when the solution is cleared or removed.
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.Telemetry; using Microsoft.CodeAnalysis.Diagnostics.Telemetry;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Microsoft.CodeAnalysis.Workspaces.Diagnostics;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -39,6 +40,20 @@ public DiagnosticComputer(Project project) ...@@ -39,6 +40,20 @@ public DiagnosticComputer(Project project)
return DiagnosticAnalysisResultMap.Create(ImmutableDictionary<string, DiagnosticAnalysisResultBuilder>.Empty, ImmutableDictionary<string, AnalyzerTelemetryInfo>.Empty); 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); var compilation = await _project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
// TODO: can we support analyzerExceptionFilter in remote host? // TODO: can we support analyzerExceptionFilter in remote host?
...@@ -70,9 +85,10 @@ public DiagnosticComputer(Project project) ...@@ -70,9 +85,10 @@ public DiagnosticComputer(Project project)
var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken); var builderMap = analysisResult.ToResultBuilderMap(_project, VersionStamp.Default, compilation, analysisResult.Analyzers, cancellationToken);
return DiagnosticAnalysisResultMap.Create(builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value), return DiagnosticAnalysisResultMap.Create(
analysisResult.AnalyzerTelemetryInfo.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value), builderMap.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value),
_exceptions.ToImmutableDictionary(kv => GetAnalyzerId(analyzerMap, kv.Key), kv => kv.Value.ToImmutableArray())); 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) private void OnAnalyzerException(Exception exception, DiagnosticAnalyzer analyzer, Diagnostic diagnostic)
......
...@@ -68,7 +68,9 @@ ...@@ -68,7 +68,9 @@
<Compile Include="Services\AssetSource.cs" /> <Compile Include="Services\AssetSource.cs" />
<Compile Include="Services\AssetService.cs" /> <Compile Include="Services\AssetService.cs" />
<Compile Include="Services\AssetStorage.cs" /> <Compile Include="Services\AssetStorage.cs" />
<Compile Include="Services\ChecksumSourceText.cs" />
<Compile Include="Services\CompilationService.cs" /> <Compile Include="Services\CompilationService.cs" />
<Compile Include="Services\ProjectCacheHostServiceFactory.cs" />
<Compile Include="Services\RoslynServices.cs" /> <Compile Include="Services\RoslynServices.cs" />
<Compile Include="Services\SolutionService.cs" /> <Compile Include="Services\SolutionService.cs" />
<Compile Include="Storage\RemotePersistentStorageLocationService.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 ...@@ -102,7 +102,9 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
var textLoader = TextLoader.From( var textLoader = TextLoader.From(
TextAndVersion.Create( 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(), VersionStamp.Create(),
documentInfo.FilePath)); documentInfo.FilePath));
...@@ -155,7 +157,9 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc ...@@ -155,7 +157,9 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
var textLoader = TextLoader.From( var textLoader = TextLoader.From(
TextAndVersion.Create( 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(), VersionStamp.Create(),
documentInfo.FilePath)); documentInfo.FilePath));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册