Skip to content

Commit

Permalink
Merge pull request #50762 from CyrusNajmabadi/cloudCache
Browse files Browse the repository at this point in the history
Provide a new implementation of IPersistenceService that sits on top of the new platform 'cloud cache' system.
  • Loading branch information
msftbot[bot] authored Mar 9, 2021
2 parents 9f95d53 + 89e1b51 commit 1303eef
Show file tree
Hide file tree
Showing 47 changed files with 1,519 additions and 303 deletions.
5 changes: 3 additions & 2 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
<MicrosoftBuildTasksCoreVersion>$(MicrosoftBuildPackagesVersion)</MicrosoftBuildTasksCoreVersion>
<NuGetVisualStudioContractsVersion>5.7.0</NuGetVisualStudioContractsVersion>
<!-- This is working around Microsoft.VisualStudio.Shell.15.0 having an unstated conflicting reference on this with NuGet.VisualStudio.Contracts -->
<MicrosoftVisualStudioRpcContractsVersion>16.9.63</MicrosoftVisualStudioRpcContractsVersion>
<MicrosoftVisualStudioRpcContractsVersion>16.10.11-alpha</MicrosoftVisualStudioRpcContractsVersion>
<!--
Since the Microsoft.CodeAnalysis.Analyzers package is a public dependency of our NuGet
packages we will keep it untied to the RoslynDiagnosticsNugetPackageVersion we use for
Expand Down Expand Up @@ -116,6 +116,7 @@
<MicrosoftServiceHubClientVersion>2.7.339</MicrosoftServiceHubClientVersion>
<MicrosoftServiceHubFrameworkVersion>2.7.339</MicrosoftServiceHubFrameworkVersion>
<MicrosoftVisualBasicVersion>10.1.0</MicrosoftVisualBasicVersion>
<MicrosoftVisualStudioCacheVersion>16.10.40-alpha</MicrosoftVisualStudioCacheVersion>
<MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>15.8.27812-alpha</MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>
<MicrosoftVisualStudioCodeAnalysisSdkUIVersion>15.8.27812-alpha</MicrosoftVisualStudioCodeAnalysisSdkUIVersion>
<MicrosoftVisualStudioComponentModelHostVersion>16.9.184-preview</MicrosoftVisualStudioComponentModelHostVersion>
Expand Down Expand Up @@ -216,7 +217,7 @@
<SystemIOFileSystemVersion>4.3.0</SystemIOFileSystemVersion>
<SystemIOFileSystemPrimitivesVersion>4.3.0</SystemIOFileSystemPrimitivesVersion>
<SystemIOPipesAccessControlVersion>4.5.1</SystemIOPipesAccessControlVersion>
<SystemIOPipelinesVersion>5.0.0</SystemIOPipelinesVersion>
<SystemIOPipelinesVersion>5.0.1</SystemIOPipelinesVersion>
<SystemManagementVersion>5.0.0-preview.8.20407.11</SystemManagementVersion>
<SystemMemoryVersion>4.5.4</SystemMemoryVersion>
<SystemResourcesExtensionsVersion>4.7.1</SystemResourcesExtensionsVersion>
Expand Down
9 changes: 3 additions & 6 deletions src/Tools/IdeBenchmarks/SQLitePersistentStorageBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,14 @@ public void GlobalSetup()

// Explicitly choose the sqlite db to test.
_workspace.TryApplyChanges(_workspace.CurrentSolution.WithOptions(_workspace.Options
.WithChangedOption(StorageOptions.Database, StorageDatabase.SQLite)));
.WithChangedOption(StorageOptions.Database, StorageDatabase.SQLite)
.WithChangedOption(StorageOptions.DatabaseMustSucceed, true)));

var connectionPoolService = _workspace.ExportProvider.GetExportedValue<SQLiteConnectionPoolService>();
_storageService = new SQLitePersistentStorageService(connectionPoolService, new LocationService());
_storageService = new SQLitePersistentStorageService(_workspace.Options, connectionPoolService, new LocationService());

var solution = _workspace.CurrentSolution;
_storage = _storageService.GetStorageWorkerAsync(_workspace, SolutionKey.ToSolutionKey(solution), solution, CancellationToken.None).AsTask().GetAwaiter().GetResult();
if (_storage == NoOpPersistentStorage.Instance)
{
throw new InvalidOperationException("We didn't properly get the sqlite storage instance.");
}

Console.WriteLine("Storage type: " + _storage.GetType());
_document = _workspace.CurrentSolution.Projects.Single().Documents.Single();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Composition;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Storage;
using Microsoft.CodeAnalysis.Storage.CloudCache;
using Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks;

namespace CloudCache
{
[ExportWorkspaceService(typeof(ICloudCacheStorageServiceFactory), ServiceLayer.Host), Shared]
internal class IdeCoreBenchmarksCloudCacheServiceProvider : ICloudCacheStorageServiceFactory
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public IdeCoreBenchmarksCloudCacheServiceProvider()
{
Console.WriteLine($"Instantiated {nameof(IdeCoreBenchmarksCloudCacheServiceProvider)}");
}

public AbstractPersistentStorageService Create(IPersistentStorageLocationService locationService)
{
return new MockCloudCachePersistentStorageService(
locationService, @"C:\github\roslyn", cs =>
{
if (cs is IAsyncDisposable asyncDisposable)
{
asyncDisposable.DisposeAsync().AsTask().Wait();
}
else if (cs is IDisposable disposable)
{
disposable.Dispose();
}
});
}
}
}
149 changes: 81 additions & 68 deletions src/Tools/IdeCoreBenchmarks/FindReferencesBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
#nullable disable

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using AnalyzerRunner;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.Storage;

Expand All @@ -23,77 +27,86 @@ namespace IdeCoreBenchmarks
[MemoryDiagnoser]
public class FindReferencesBenchmarks
{
private readonly string _solutionPath;

private MSBuildWorkspace _workspace;

public FindReferencesBenchmarks()
{
var roslynRoot = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
_solutionPath = Path.Combine(roslynRoot, @"C:\github\roslyn\Roslyn.sln");

if (!File.Exists(_solutionPath))
throw new ArgumentException("Couldn't find Roslyn.sln");

Console.Write("Found roslyn.sln: " + Process.GetCurrentProcess().Id);
}

[GlobalSetup]
public void Setup()
{
_workspace = AnalyzerRunnerHelper.CreateWorkspace();
if (_workspace == null)
throw new ArgumentException("Couldn't create workspace");

_workspace.TryApplyChanges(_workspace.CurrentSolution.WithOptions(_workspace.Options
.WithChangedOption(StorageOptions.Database, StorageDatabase.SQLite)));

Console.WriteLine("Opening roslyn. Attach to: " + Process.GetCurrentProcess().Id);

var start = DateTime.Now;
_ = _workspace.OpenSolutionAsync(_solutionPath, progress: null, CancellationToken.None).Result;
Console.WriteLine("Finished opening roslyn: " + (DateTime.Now - start));

// Force a storage instance to be created. This makes it simple to go examine it prior to any operations we
// perform, including seeing how big the initial string table is.
var storageService = _workspace.Services.GetService<IPersistentStorageService>();
if (storageService == null)
throw new ArgumentException("Couldn't get storage service");

using var storage = storageService.GetStorageAsync(_workspace.CurrentSolution, CancellationToken.None).AsTask().GetAwaiter().GetResult();
}

[GlobalCleanup]
public void Cleanup()
{
_workspace?.Dispose();
_workspace = null;
}

[Benchmark]
public async Task RunFindReferences()
{
var solution = _workspace.CurrentSolution;

// There might be multiple projects with this name. That's ok. FAR goes and finds all the linked-projects
// anyways to perform the search on all the equivalent symbols from them. So the end perf cost is the
// same.
var project = solution.Projects.First(p => p.AssemblyName == "Microsoft.CodeAnalysis.CSharp");

var start = DateTime.Now;
var compilation = await project.GetCompilationAsync();
Console.WriteLine("Time to get first compilation: " + (DateTime.Now - start));
var type = compilation.GetTypeByMetadataName("Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.LanguageParser");
if (type == null)
throw new Exception("Couldn't find type");

start = DateTime.Now;
var references = await SymbolFinder.FindReferencesAsync(type, solution);
Console.WriteLine("Time to find-refs: " + (DateTime.Now - start));
var refList = references.ToList();
Console.WriteLine($"References count: {refList.Count}");
var locations = refList.SelectMany(r => r.Locations).ToList();
Console.WriteLine($"Locations count: {locations.Count}");
try
{
// QueryVisualStudioInstances returns Visual Studio installations on .NET Framework, and .NET Core SDK
// installations on .NET Core. We use the one with the most recent version.
var msBuildInstance = MSBuildLocator.QueryVisualStudioInstances().OrderByDescending(x => x.Version).First();

MSBuildLocator.RegisterInstance(msBuildInstance);

var roslynRoot = Environment.GetEnvironmentVariable(Program.RoslynRootPathEnvVariableName);
var solutionPath = Path.Combine(roslynRoot, @"C:\github\roslyn\Compilers.sln");

if (!File.Exists(solutionPath))
throw new ArgumentException("Couldn't find Compilers.sln");

Console.Write("Found Compilers.sln: " + Process.GetCurrentProcess().Id);

var assemblies = MSBuildMefHostServices.DefaultAssemblies
.Add(typeof(AnalyzerRunnerHelper).Assembly)
.Add(typeof(FindReferencesBenchmarks).Assembly);
var services = MefHostServices.Create(assemblies);

var workspace = MSBuildWorkspace.Create(new Dictionary<string, string>
{
// Use the latest language version to force the full set of available analyzers to run on the project.
{ "LangVersion", "9.0" },
}, services);

if (workspace == null)
throw new ArgumentException("Couldn't create workspace");

workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options
.WithChangedOption(StorageOptions.Database, StorageDatabase.SQLite)
.WithChangedOption(StorageOptions.DatabaseMustSucceed, true)));

Console.WriteLine("Opening roslyn. Attach to: " + Process.GetCurrentProcess().Id);

var start = DateTime.Now;
var solution = workspace.OpenSolutionAsync(solutionPath, progress: null, CancellationToken.None).Result;
Console.WriteLine("Finished opening roslyn: " + (DateTime.Now - start));

// Force a storage instance to be created. This makes it simple to go examine it prior to any operations we
// perform, including seeing how big the initial string table is.
var storageService = workspace.Services.GetService<IPersistentStorageService>();
if (storageService == null)
throw new ArgumentException("Couldn't get storage service");

using (var storage = await storageService.GetStorageAsync(workspace.CurrentSolution, CancellationToken.None))
{
Console.WriteLine();
}

// There might be multiple projects with this name. That's ok. FAR goes and finds all the linked-projects
// anyways to perform the search on all the equivalent symbols from them. So the end perf cost is the
// same.
var project = solution.Projects.First(p => p.AssemblyName == "Microsoft.CodeAnalysis");

start = DateTime.Now;
var compilation = await project.GetCompilationAsync();
Console.WriteLine("Time to get first compilation: " + (DateTime.Now - start));
var type = compilation.GetTypeByMetadataName("Microsoft.CodeAnalysis.SyntaxToken");
if (type == null)
throw new Exception("Couldn't find type");

Console.WriteLine("Starting find-refs");
start = DateTime.Now;
var references = await SymbolFinder.FindReferencesAsync(type, solution);
Console.WriteLine("Time to find-refs: " + (DateTime.Now - start));
var refList = references.ToList();
Console.WriteLine($"References count: {refList.Count}");
var locations = refList.SelectMany(r => r.Locations).ToList();
Console.WriteLine($"Locations count: {locations.Count}");
}
catch (ReflectionTypeLoadException ex)
{
foreach (var ex2 in ex.LoaderExceptions)
Console.WriteLine(ex2);
}
}
}
}
21 changes: 21 additions & 0 deletions src/Tools/IdeCoreBenchmarks/IdeCoreBenchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,34 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<!-- Automatically generate the necessary assembly binding redirects -->
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<LangVersion>9</LangVersion>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\..\VisualStudio\Core\Def\Storage\AbstractCloudCachePersistentStorageService.cs" Link="CloudCache\AbstractCloudCachePersistentStorageService.cs" />
<Compile Include="..\..\VisualStudio\Core\Def\Storage\CloudCachePersistentStorage.cs" Link="CloudCache\CloudCachePersistentStorage.cs" />
<Compile Include="..\..\VisualStudio\Core\Def\Storage\ProjectContainerKeyCache.cs" Link="CloudCache\ProjectContainerKeyCache.cs" />
<Compile Include="..\..\VisualStudio\CSharp\Test\PersistentStorage\Mocks\AuthorizationServiceMock.cs" Link="CloudCache\AuthorizationServiceMock.cs" />
<Compile Include="..\..\VisualStudio\CSharp\Test\PersistentStorage\Mocks\FileSystemServiceMock.cs" Link="CloudCache\FileSystemServiceMock.cs" />
<Compile Include="..\..\VisualStudio\CSharp\Test\PersistentStorage\Mocks\MockCloudCachePersistentStorageService.cs" Link="CloudCache\MockCloudCachePersistentStorageService.cs" />
<Compile Include="..\..\VisualStudio\CSharp\Test\PersistentStorage\Mocks\ServiceBrokerMock.cs" Link="CloudCache\ServiceBrokerMock.cs" />
<Compile Include="..\..\VisualStudio\CSharp\Test\PersistentStorage\Mocks\SolutionServiceMock.cs" Link="CloudCache\SolutionServiceMock.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="$(BenchmarkDotNetVersion)" />
<!-- This is to avoid a version conflict during build -->
<PackageReference Include="System.CodeDom" Version="$(SystemCodeDomVersion)" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkVersion)" ExcludeAssets="Runtime" PrivateAssets="All" />

<PackageReference Include="Microsoft.VisualStudio.Composition" Version="$(MicrosoftVisualStudioCompositionVersion)" />
<PackageReference Include="Microsoft.Build.Locator" Version="$(MicrosoftBuildLocatorVersion)" />
<PackageReference Include="System.Buffers" Version="$(SystemBuffersVersion)" />
<PackageReference Include="System.ComponentModel.Composition" Version="$(SystemComponentModelCompositionVersion)" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="$(SystemThreadingTasksDataflowVersion)" />
<PackageReference Include="Microsoft.Win32.Registry" Version="$(MicrosoftWin32RegistryVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />
<PackageReference Include="Microsoft.VisualStudio.Cache" Version="$(MicrosoftVisualStudioCacheVersion)" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 1303eef

Please sign in to comment.