Skip to content

Commit

Permalink
RemoteHostOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Feb 16, 2022
1 parent f77dce9 commit d042867
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
Expand Down Expand Up @@ -35,11 +33,6 @@ internal sealed class RemoteHostOptions : IOptionProvider
FeatureName, nameof(OOP64Bit), defaultValue: true,
storageLocation: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OOP64Bit)));

// use Server GC for 64-bit OOP
public static readonly Option2<bool> OOPServerGC = new(
FeatureName, nameof(OOPServerGC), defaultValue: false,
storageLocation: new LocalUserProfileStorageLocation(LocalRegistryPath + nameof(OOPServerGC)));

public static readonly Option2<bool> OOPServerGCFeatureFlag = new(
FeatureName, nameof(OOPServerGCFeatureFlag), defaultValue: false,
new FeatureFlagStorageLocation("Roslyn.OOPServerGC"));
Expand All @@ -52,7 +45,6 @@ internal sealed class RemoteHostOptions : IOptionProvider
ImmutableArray<IOption> IOptionProvider.Options { get; } = ImmutableArray.Create<IOption>(
SolutionChecksumMonitorBackOffTimeSpanInMS,
OOP64Bit,
OOPServerGC,
OOPServerGCFeatureFlag,
OOPCoreClrFeatureFlag);

Expand All @@ -61,21 +53,5 @@ internal sealed class RemoteHostOptions : IOptionProvider
public RemoteHostOptions()
{
}

public static bool IsServiceHubProcessServerGC(IGlobalOptionService globalOptions)
=> globalOptions.GetOption(OOPServerGC) || globalOptions.GetOption(OOPServerGCFeatureFlag);

/// <summary>
/// Determines whether ServiceHub out-of-process execution is enabled for Roslyn.
/// </summary>
public static bool IsUsingServiceHubOutOfProcess(IGlobalOptionService globalOptions)
=> Environment.Is64BitOperatingSystem && globalOptions.GetOption(OOP64Bit);

public static bool IsServiceHubProcessCoreClr(IGlobalOptionService globalOptions)
=> globalOptions.GetOption(OOPCoreClrFeatureFlag);

public static bool IsCurrentProcessRunningOnCoreClr()
=> !RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework") &&
!RuntimeInformation.FrameworkDescription.StartsWith(".NET Native");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
// We don't want to bring up the OOP process in a VS cloud environment client instance
// Avoids proffering brokered services on the client instance.
if (!RemoteHostOptions.IsUsingServiceHubOutOfProcess(_globalOptions) ||
if (!_globalOptions.GetOption(RemoteHostOptions.OOP64Bit) ||
workspaceServices.Workspace is not VisualStudioWorkspace ||
workspaceServices.GetRequiredService<IWorkspaceContextService>().IsCloudEnvironmentClient())
{
Expand Down Expand Up @@ -99,8 +99,12 @@ private VisualStudioRemoteHostClientProvider(
var brokeredServiceContainer = await _vsServiceProvider.GetServiceAsync<SVsBrokeredServiceContainer, IBrokeredServiceContainer>().ConfigureAwait(false);
var serviceBroker = brokeredServiceContainer.GetFullAccessServiceBroker();

var configuration =
(_globalOptions.GetOption(RemoteHostOptions.OOPCoreClrFeatureFlag) ? RemoteProcessConfiguration.Core : 0) |
(_globalOptions.GetOption(RemoteHostOptions.OOPServerGCFeatureFlag) ? RemoteProcessConfiguration.ServerGC : 0);

// VS AsyncLazy does not currently support cancellation:
var client = await ServiceHubRemoteHostClient.CreateAsync(_services, _globalOptions, _listenerProvider, serviceBroker, _callbackDispatchers, CancellationToken.None).ConfigureAwait(false);
var client = await ServiceHubRemoteHostClient.CreateAsync(_services, configuration, _listenerProvider, serviceBroker, _callbackDispatchers, CancellationToken.None).ConfigureAwait(false);

// proffer in-proc brokered services:
_ = brokeredServiceContainer.Proffer(SolutionAssetProvider.ServiceDescriptor, (_, _, _, _) => ValueTaskFactory.FromResult<object?>(new SolutionAssetProvider(_services)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
<ProjectReference Include="..\..\..\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj" />
<ProjectReference Include="..\..\..\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj" />
<ProjectReference Include="..\..\..\Interactive\Host\Microsoft.CodeAnalysis.InteractiveHost.csproj" Aliases="InteractiveHost" />
<ProjectReference Include="..\..\..\Workspaces\Remote\Core\Microsoft.CodeAnalysis.Remote.Workspaces.csproj" />
</ItemGroup>
<ItemGroup Label="File References">
<Reference Include="System.ComponentModel.Composition" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
_threadingContext = componentModel.GetService<IThreadingContext>();
var globalOptions = componentModel.GetService<IGlobalOptionService>();

var workspace = componentModel.GetService<VisualStudioWorkspace>();
_workspace = componentModel.GetService<VisualStudioWorkspace>();
_ = new ForceLowMemoryMode(globalOptions);

// Add our command handlers for menu (commands must exist in the .vsct file)
Expand All @@ -96,7 +96,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
}

// set logger at start up
PerformanceLoggersPage.SetLoggers(globalOptions, _threadingContext, workspace.Services);
PerformanceLoggersPage.SetLoggers(globalOptions, _threadingContext, _workspace.Services);
}
#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public RemoteWorkspace GetRemoteWorkspace()

public override RemoteServiceConnection<T> CreateConnection<T>(object? callbackTarget) where T : class
{
var descriptor = ServiceDescriptors.Instance.GetServiceDescriptor(typeof(T), isRemoteHostServerGC: GCSettings.IsServerGC, isRemoteHostCoreClr: RemoteHostOptions.IsCurrentProcessRunningOnCoreClr());
var descriptor = ServiceDescriptors.Instance.GetServiceDescriptor(typeof(T), RemoteProcessConfiguration.ServerGC | (ServiceDescriptors.IsCurrentProcessRunningOnCoreClr() ? RemoteProcessConfiguration.Core : 0));
var callbackDispatcher = (descriptor.ClientInterface != null) ? _callbackDispatchers.GetDispatcher(typeof(T)) : null;

return new BrokeredServiceConnection<T>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Remote;

namespace Microsoft.CodeAnalysis.ExternalAccess.UnitTesting.Api
Expand All @@ -33,13 +32,6 @@ internal UnitTestingRemoteHostClient(ServiceHubRemoteHostClient client, UnitTest
return new UnitTestingRemoteHostClient((ServiceHubRemoteHostClient)client, serviceDescriptors, callbackDispatchers);
}

[Obsolete("Use UnitTestingGlobalOptions.IsServiceHubProcessCoreClr instead")]
public static bool IsServiceHubProcessCoreClr(HostWorkspaceServices services)
{
var optionServices = services.GetRequiredService<IOptionService>();
return optionServices.GetOption(RemoteHostOptions.OOPCoreClrFeatureFlag);
}

public UnitTestingRemoteServiceConnectionWrapper<TService> CreateConnection<TService>(object? callbackTarget) where TService : class
=> new(_client.CreateConnection<TService>(_serviceDescriptors.UnderlyingObject, _callbackDispatchers, callbackTarget));

Expand Down
22 changes: 22 additions & 0 deletions src/Workspaces/Remote/Core/RemoteProcessConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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;

namespace Microsoft.CodeAnalysis.Remote
{
[Flags]
internal enum RemoteProcessConfiguration
{
/// <summary>
/// Remote host runs on .NET 6+.
/// </summary>
Core = 1,

/// <summary>
/// Remote host uses server GC.
/// </summary>
ServerGC = 1 << 1
}
}
20 changes: 13 additions & 7 deletions src/Workspaces/Remote/Core/ServiceDescriptors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CodeLens;
Expand Down Expand Up @@ -120,18 +121,23 @@ internal static string GetSimpleName(Type serviceInterface)
return (descriptor64, descriptor64ServerGC, descriptorCoreClr64, descriptorCoreClr64ServerGC);
}

public static bool IsCurrentProcessRunningOnCoreClr()
=> !RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework") &&
!RuntimeInformation.FrameworkDescription.StartsWith(".NET Native");

public ServiceDescriptor GetServiceDescriptorForServiceFactory(Type serviceType)
=> GetServiceDescriptor(serviceType, isRemoteHostServerGC: GCSettings.IsServerGC, isRemoteHostCoreClr: RemoteHostOptions.IsCurrentProcessRunningOnCoreClr());
=> GetServiceDescriptor(serviceType, RemoteProcessConfiguration.ServerGC | (IsCurrentProcessRunningOnCoreClr() ? RemoteProcessConfiguration.Core : 0));

public ServiceDescriptor GetServiceDescriptor(Type serviceType, bool isRemoteHostServerGC, bool isRemoteHostCoreClr)
public ServiceDescriptor GetServiceDescriptor(Type serviceType, RemoteProcessConfiguration configuration)
{
var (descriptor64, descriptor64ServerGC, descriptorCoreClr64, descriptorCoreClr64ServerGC) = _descriptors[serviceType];
return (isRemoteHostServerGC, isRemoteHostCoreClr) switch
return (configuration & (RemoteProcessConfiguration.Core | RemoteProcessConfiguration.ServerGC)) switch
{
(false, false) => descriptor64,
(false, true) => descriptorCoreClr64,
(true, false) => descriptor64ServerGC,
(true, true) => descriptorCoreClr64ServerGC,
0 => descriptor64,
RemoteProcessConfiguration.Core => descriptorCoreClr64,
RemoteProcessConfiguration.ServerGC => descriptor64ServerGC,
RemoteProcessConfiguration.Core | RemoteProcessConfiguration.ServerGC => descriptorCoreClr64ServerGC,
_ => throw ExceptionUtilities.Unreachable
};
}

Expand Down
14 changes: 6 additions & 8 deletions src/Workspaces/Remote/Core/ServiceHubRemoteHostClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ internal sealed partial class ServiceHubRemoteHostClient : RemoteHostClient
private readonly IRemoteHostClientShutdownCancellationService? _shutdownCancellationService;
private readonly IRemoteServiceCallbackDispatcherProvider _callbackDispatcherProvider;

private readonly bool _isRemoteHostServerGC;
private readonly bool _isRemoteHostCoreClr;
public readonly RemoteProcessConfiguration Configuration;

private ServiceHubRemoteHostClient(
HostWorkspaceServices services,
IGlobalOptionService globalOptions,
RemoteProcessConfiguration configuration,
ServiceBrokerClient serviceBrokerClient,
HubClient hubClient,
IRemoteServiceCallbackDispatcherProvider callbackDispatcherProvider)
Expand All @@ -53,13 +52,12 @@ private ServiceHubRemoteHostClient(
_assetStorage = services.GetRequiredService<ISolutionAssetStorageProvider>().AssetStorage;
_errorReportingService = services.GetService<IErrorReportingService>();
_shutdownCancellationService = services.GetService<IRemoteHostClientShutdownCancellationService>();
_isRemoteHostServerGC = RemoteHostOptions.IsServiceHubProcessServerGC(globalOptions);
_isRemoteHostCoreClr = RemoteHostOptions.IsServiceHubProcessCoreClr(globalOptions);
Configuration = configuration;
}

public static async Task<RemoteHostClient> CreateAsync(
HostWorkspaceServices services,
IGlobalOptionService globalOptions,
RemoteProcessConfiguration configuration,
AsynchronousOperationListenerProvider listenerProvider,
IServiceBroker serviceBroker,
RemoteServiceCallbackDispatcherRegistry callbackDispatchers,
Expand All @@ -74,7 +72,7 @@ public static async Task<RemoteHostClient> CreateAsync(

var hubClient = new HubClient("ManagedLanguage.IDE.RemoteHostClient");

var client = new ServiceHubRemoteHostClient(services, globalOptions, serviceBrokerClient, hubClient, callbackDispatchers);
var client = new ServiceHubRemoteHostClient(services, configuration, serviceBrokerClient, hubClient, callbackDispatchers);

var syntaxTreeConfigurationService = services.GetService<ISyntaxTreeConfigurationService>();
if (syntaxTreeConfigurationService != null)
Expand Down Expand Up @@ -104,7 +102,7 @@ public override RemoteServiceConnection<T> CreateConnection<T>(object? callbackT
/// </summary>
internal RemoteServiceConnection<T> CreateConnection<T>(ServiceDescriptors descriptors, IRemoteServiceCallbackDispatcherProvider callbackDispatcherProvider, object? callbackTarget) where T : class
{
var descriptor = descriptors.GetServiceDescriptor(typeof(T), _isRemoteHostServerGC, _isRemoteHostCoreClr);
var descriptor = descriptors.GetServiceDescriptor(typeof(T), Configuration);
var callbackDispatcher = (descriptor.ClientInterface != null) ? callbackDispatcherProvider.GetDispatcher(typeof(T)) : null;

return new BrokeredServiceConnection<T>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace Microsoft.CodeAnalysis.Remote
{
/// <summary>
/// This service is used by the <see cref="SolutionChecksumUpdater"/> to proactively update the solution snapshot in
/// This service is used by the SolutionChecksumUpdater to proactively update the solution snapshot in
/// the out-of-process workspace. We do this to limit the amount of time required to synchronize a solution over after an edit
/// once a feature is asking for a snapshot.
/// </summary>
Expand Down

0 comments on commit d042867

Please sign in to comment.