提交 2325f6b0 编写于 作者: H Heejae Chang

added ability to run OOP in 64bit. currently it is not enabled. but it can be...

added ability to run OOP in 64bit. currently it is not enabled. but it can be enabled explicitly through options or remotely through a/b testing.

a/b testing is not enabled yet.
上级 b3368765
......@@ -109,7 +109,7 @@ public class ServiceProvider : IServiceProvider
public ServiceProvider(bool runCacheCleanup)
{
_storage = runCacheCleanup ?
new AssetStorage(cleanupInterval: TimeSpan.FromSeconds(30), purgeAfter: TimeSpan.FromMinutes(1)) :
new AssetStorage(cleanupInterval: TimeSpan.FromSeconds(30), purgeAfter: TimeSpan.FromMinutes(1), gcAfter: TimeSpan.FromMinutes(5)) :
new AssetStorage();
}
......
......@@ -15,8 +15,10 @@ namespace Microsoft.CodeAnalysis.Diagnostics
{
internal static class DiagnosticResultSerializer
{
public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
public static (int diagnostics, int telemetry, int exceptions) Serialize(
ObjectWriter writer, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
{
var diagnosticCount = 0;
var diagnosticSerializer = new DiagnosticDataSerializer(VersionStamp.Default, VersionStamp.Default);
var analysisResult = result.AnalysisResult;
......@@ -26,11 +28,12 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st
{
writer.WriteString(kv.Key);
Serialize(writer, diagnosticSerializer, kv.Value.SyntaxLocals, cancellationToken);
Serialize(writer, diagnosticSerializer, kv.Value.SemanticLocals, cancellationToken);
Serialize(writer, diagnosticSerializer, kv.Value.NonLocals, cancellationToken);
diagnosticCount += Serialize(writer, diagnosticSerializer, kv.Value.SyntaxLocals, cancellationToken);
diagnosticCount += Serialize(writer, diagnosticSerializer, kv.Value.SemanticLocals, cancellationToken);
diagnosticCount += Serialize(writer, diagnosticSerializer, kv.Value.NonLocals, cancellationToken);
diagnosticSerializer.WriteTo(writer, kv.Value.Others, cancellationToken);
diagnosticCount += kv.Value.Others.Length;
}
var telemetryInfo = result.TelemetryInfo;
......@@ -50,6 +53,9 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st
writer.WriteString(kv.Key);
diagnosticSerializer.WriteTo(writer, kv.Value, cancellationToken);
}
// report how many data has been sent
return (diagnosticCount, telemetryInfo.Count, exceptions.Count);
}
public static DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult> Deserialize(
......@@ -103,18 +109,24 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st
return DiagnosticAnalysisResultMap.Create(analysisMap.ToImmutable(), telemetryMap.ToImmutable(), exceptionMap.ToImmutable());
}
private static void Serialize(
private static int Serialize(
ObjectWriter writer,
DiagnosticDataSerializer serializer,
ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>> diagnostics,
CancellationToken cancellationToken)
{
var count = 0;
writer.WriteInt32(diagnostics.Count);
foreach (var kv in diagnostics)
{
kv.Key.WriteTo(writer);
serializer.WriteTo(writer, kv.Value, cancellationToken);
count += kv.Value.Length;
}
return count;
}
private static ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>> Deserialize(
......
......@@ -70,7 +70,12 @@ Public Class BuildDevDivInsertionFiles
"StreamJsonRpc.resources.dll",
"codeAnalysisService.servicehub.service.json",
"remoteHostService.servicehub.service.json",
"serviceHubSnapshotService.servicehub.service.json",
"snapshotService.servicehub.service.json",
"remoteSymbolSearchUpdateEngine.servicehub.service.json",
"codeAnalysisService64.servicehub.service.json",
"remoteHostService64.servicehub.service.json",
"snapshotService64.servicehub.service.json",
"remoteSymbolSearchUpdateEngine64.servicehub.service.json",
"Microsoft.Build.Conversion.Core.dll",
"Microsoft.Build.dll",
"Microsoft.Build.Engine.dll",
......@@ -836,8 +841,6 @@ Public Class BuildDevDivInsertionFiles
add("Exes\VBCSCompiler\VBCSCompiler.exe.config")
add("Exes\InteractiveHost\InteractiveHost.exe.config")
add("Exes\csi\csi.rsp")
add("Vsix\Roslyn.Deployment.Full.Next\remoteSymbolSearchUpdateEngine.servicehub.service.json")
add("Vsix\Roslyn.Deployment.Full.Next\snapshotService.servicehub.service.json")
add("Vsix\VisualStudioInteractiveComponents\CSharpInteractive.rsp")
add("Vsix\VisualStudioSetup\System.Composition.Convention.dll")
add("Vsix\VisualStudioSetup\System.Composition.Hosting.dll")
......
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Execution;
using Microsoft.CodeAnalysis.Experiments;
using Microsoft.CodeAnalysis.Extensions;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -85,6 +86,9 @@ public void Enable()
return;
}
// set bitness
SetRemoteHostBitness();
// make sure we run it on background thread
_shutdownCancellationTokenSource = new CancellationTokenSource();
......@@ -157,6 +161,23 @@ public Task<RemoteHostClient> TryGetRemoteHostClientAsync(CancellationToken canc
return remoteClientTask;
}
private void SetRemoteHostBitness()
{
var x64 = _workspace.Options.GetOption(RemoteHostOptions.OOP64Bit);
if (!x64)
{
x64 = _workspace.Services.GetService<IExperimentationService>().IsExperimentEnabled(
WellKnownExperimentNames.RoslynOOP64bit);
}
// log OOP bitness
Logger.Log(FunctionId.RemoteHost_Bitness, KeyValueLogMessage.Create(LogType.Trace, m => m["64bit"] = x64));
// set service bitness
WellKnownRemoteHostServices.Set64bit(x64);
WellKnownServiceHubServices.Set64bit(x64);
}
private async Task<RemoteHostClient> EnableAsync(CancellationToken cancellationToken)
{
// if we reached here, IRemoteHostClientFactory must exist.
......
......@@ -44,6 +44,11 @@ internal static class RemoteHostOptions
nameof(InternalFeatureOnOffOptions), nameof(RestartRemoteHostAllowed), defaultValue: false,
storageLocations: new LocalUserProfileStorageLocation(InternalFeatureOnOffOptions.LocalRegistryPath + nameof(RestartRemoteHostAllowed)));
// use 64bit OOP
public static readonly Option<bool> OOP64Bit = new Option<bool>(
nameof(InternalFeatureOnOffOptions), nameof(OOP64Bit), defaultValue: false,
storageLocations: new LocalUserProfileStorageLocation(InternalFeatureOnOffOptions.LocalRegistryPath + nameof(OOP64Bit)));
public static readonly Option<bool> RemoteHostTest = new Option<bool>(nameof(InternalFeatureOnOffOptions), nameof(RemoteHostTest), defaultValue: false);
}
......@@ -55,6 +60,7 @@ internal class RemoteHostOptionsProvider : IOptionProvider
RemoteHostOptions.SolutionChecksumMonitorBackOffTimeSpanInMS,
RemoteHostOptions.RequestServiceTimeoutInMS,
RemoteHostOptions.RestartRemoteHostAllowed,
RemoteHostOptions.OOP64Bit,
RemoteHostOptions.RemoteHostTest);
}
}
......@@ -40,7 +40,7 @@ public void TestGetAssets()
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestCleanup()
{
var storage = new AssetStorage(cleanupInterval: TimeSpan.FromMilliseconds(1), purgeAfter: TimeSpan.FromMilliseconds(2));
var storage = new AssetStorage(cleanupInterval: TimeSpan.FromMilliseconds(1), purgeAfter: TimeSpan.FromMilliseconds(2), gcAfter: TimeSpan.FromMilliseconds(5));
var checksum = Checksum.Create(WellKnownSynchronizationKind.Null, ImmutableArray.CreateRange(Guid.NewGuid().ToByteArray()));
var data = new object();
......
......@@ -102,6 +102,22 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="snapshotService64.servicehub.service.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="codeAnalysisService64.servicehub.service.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="remoteHostService64.servicehub.service.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="remoteSymbolSearchUpdateEngine64.servicehub.service.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
......
{
"host": "desktopClr",
"hostId": "RoslynCodeAnalysisService64",
"hostGroupAllowed": true,
"entryPoint": {
"assemblyPath": "Microsoft.CodeAnalysis.Remote.ServiceHub.dll",
"fullClassName": "Microsoft.CodeAnalysis.Remote.CodeAnalysisService",
"appBasePath": "%VSAPPIDDIR%",
"configPath": "%PkgDefApplicationConfigFile%"
}
}
\ No newline at end of file
{
"host": "desktopClr",
"hostId": "RoslynCodeAnalysisService64",
"hostGroupAllowed": true,
"entryPoint": {
"assemblyPath": "Microsoft.CodeAnalysis.Remote.ServiceHub.dll",
"fullClassName": "Microsoft.CodeAnalysis.Remote.RemoteHostService",
"appBasePath": "%VSAPPIDDIR%",
"configPath": "%PkgDefApplicationConfigFile%"
}
}
\ No newline at end of file
{
"host": "desktopClr",
"hostId": "RoslynCodeAnalysisService64",
"hostGroupAllowed": true,
"entryPoint": {
"assemblyPath": "Microsoft.CodeAnalysis.Remote.ServiceHub.dll",
"fullClassName": "Microsoft.CodeAnalysis.Remote.RemoteSymbolSearchUpdateEngine",
"appBasePath": "%VSAPPIDDIR%",
"configPath": "%PkgDefApplicationConfigFile%"
}
}
\ No newline at end of file
{
"host": "desktopClr",
"hostId": "RoslynCodeAnalysisService64",
"hostGroupAllowed": true,
"entryPoint": {
"assemblyPath": "Microsoft.CodeAnalysis.Remote.ServiceHub.dll",
"fullClassName": "Microsoft.CodeAnalysis.Remote.SnapshotService",
"appBasePath": "%VSAPPIDDIR%",
"configPath": "%PkgDefApplicationConfigFile%"
}
}
\ No newline at end of file
......@@ -25,6 +25,10 @@
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="snapshotService.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="codeAnalysisService.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="remoteSymbolSearchUpdateEngine.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="remoteHostService64.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="snapshotService64.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="codeAnalysisService64.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="remoteSymbolSearchUpdateEngine64.servicehub.service.json" />
</Assets>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,16.0)" DisplayName="Visual Studio core editor" />
......
......@@ -20,5 +20,6 @@ internal class DefaultExperimentationService : IExperimentationService
internal static class WellKnownExperimentNames
{
public const string RoslynFeatureOOP = nameof(RoslynFeatureOOP);
public const string RoslynOOP64bit = nameof(RoslynOOP64bit);
}
}
......@@ -393,5 +393,7 @@ internal enum FunctionId
SolutionCreator_AssetDifferences,
Extension_InfoBar,
Experiment_ABTesting,
AssetStorage_ForceGC,
RemoteHost_Bitness,
}
}
......@@ -2,8 +2,13 @@
namespace Microsoft.CodeAnalysis.Remote
{
internal class WellKnownRemoteHostServices
internal static class WellKnownRemoteHostServices
{
public const string RemoteHostService = "remoteHostService";
public static void Set64bit(bool x64)
{
RemoteHostService = "remoteHostService" + (x64 ? "64" : "");
}
public static string RemoteHostService { get; private set; } = "remoteHostService";
}
}
......@@ -4,11 +4,18 @@ namespace Microsoft.CodeAnalysis.Remote
{
internal static class WellKnownServiceHubServices
{
public const string ServiceHubServiceBase_Initialize = "Initialize";
public static void Set64bit(bool x64)
{
var bit = x64 ? "64" : "";
SnapshotService = "snapshotService" + bit;
CodeAnalysisService = "codeAnalysisService" + bit;
RemoteSymbolSearchUpdateEngine = "remoteSymbolSearchUpdateEngine" + bit;
}
public const string SnapshotService = "snapshotService";
public const string CodeAnalysisService = "codeAnalysisService";
public const string RemoteSymbolSearchUpdateEngine = "remoteSymbolSearchUpdateEngine";
public static string SnapshotService { get; private set; } = "snapshotService";
public static string CodeAnalysisService { get; private set; } = "codeAnalysisService";
public static string RemoteSymbolSearchUpdateEngine { get; private set; } = "remoteSymbolSearchUpdateEngine";
// CodeLens methods.
public const string CodeAnalysisService_GetReferenceCountAsync = "GetReferenceCountAsync";
......@@ -16,8 +23,9 @@ internal static class WellKnownServiceHubServices
public const string CodeAnalysisService_FindReferenceMethodsAsync = "FindReferenceMethodsAsync";
public const string CodeAnalysisService_GetFullyQualifiedName = "GetFullyQualifiedName";
public const string CodeAnalysisService_CalculateDiagnosticsAsync = "CalculateDiagnosticsAsync";
public const string ServiceHubServiceBase_Initialize = "Initialize";
public const string AssetService_RequestAssetAsync = "RequestAssetAsync";
public const string CodeAnalysisService_CalculateDiagnosticsAsync = "CalculateDiagnosticsAsync";
}
}
......@@ -18,10 +18,12 @@ namespace Microsoft.CodeAnalysis.Remote
internal class AssetStorage
{
// TODO: think of a way to use roslyn option service in OOP
public static readonly AssetStorage Default = new AssetStorage(cleanupInterval: TimeSpan.FromMinutes(1), purgeAfter: TimeSpan.FromMinutes(3));
public static readonly AssetStorage Default =
new AssetStorage(cleanupInterval: TimeSpan.FromMinutes(1), purgeAfter: TimeSpan.FromMinutes(3), gcAfter: TimeSpan.FromMinutes(5));
private readonly TimeSpan _cleanupIntervalTimeSpan;
private readonly TimeSpan _purgeAfterTimeSpan;
private readonly TimeSpan _gcAfterTimeSpan;
private readonly ConcurrentDictionary<Checksum, Entry> _globalAssets =
new ConcurrentDictionary<Checksum, Entry>(concurrencyLevel: 4, capacity: 10);
......@@ -29,6 +31,9 @@ internal class AssetStorage
private readonly ConcurrentDictionary<Checksum, Entry> _assets =
new ConcurrentDictionary<Checksum, Entry>(concurrencyLevel: 4, capacity: 10);
private DateTime _lastGCRun;
private DateTime _lastActivityTime;
private volatile AssetSource _assetSource;
public AssetStorage()
......@@ -36,10 +41,14 @@ public AssetStorage()
// constructor for testing
}
public AssetStorage(TimeSpan cleanupInterval, TimeSpan purgeAfter)
public AssetStorage(TimeSpan cleanupInterval, TimeSpan purgeAfter, TimeSpan gcAfter)
{
_cleanupIntervalTimeSpan = cleanupInterval;
_purgeAfterTimeSpan = purgeAfter;
_gcAfterTimeSpan = gcAfter;
_lastActivityTime = DateTime.UtcNow;
_lastGCRun = DateTime.UtcNow;
Task.Run(CleanAssetsAsync, CancellationToken.None);
}
......@@ -56,16 +65,22 @@ public void SetAssetSource(AssetSource assetSource)
public bool TryAddGlobalAsset(Checksum checksum, object value)
{
UpdateLastActivityTime();
return _globalAssets.TryAdd(checksum, new Entry(value));
}
public bool TryAddAsset(Checksum checksum, object value)
{
UpdateLastActivityTime();
return _assets.TryAdd(checksum, new Entry(value));
}
public IEnumerable<T> GetGlobalAssetsOfType<T>(CancellationToken cancellationToken)
{
UpdateLastActivityTime();
foreach (var asset in _globalAssets)
{
cancellationToken.ThrowIfCancellationRequested();
......@@ -80,6 +95,8 @@ public IEnumerable<T> GetGlobalAssetsOfType<T>(CancellationToken cancellationTok
public bool TryGetAsset<T>(Checksum checksum, out T value)
{
UpdateLastActivityTime();
value = default(T);
using (Logger.LogBlock(FunctionId.AssetStorage_TryGetAsset, Checksum.GetChecksumLogInfo, checksum, CancellationToken.None))
{
......@@ -97,6 +114,11 @@ public bool TryGetAsset<T>(Checksum checksum, out T value)
}
}
public void UpdateLastActivityTime()
{
_lastActivityTime = DateTime.UtcNow;
}
private void Update(Checksum checksum, Entry entry)
{
// entry is reference type. we update it directly.
......@@ -110,14 +132,50 @@ private async Task CleanAssetsAsync()
{
CleanAssets();
ForceGC();
await Task.Delay(_cleanupIntervalTimeSpan).ConfigureAwait(false);
}
}
private void CleanAssets()
private void ForceGC()
{
// if there was no activity since last GC run. we don't have anything to do
if (_lastGCRun >= _lastActivityTime)
{
return;
}
var current = DateTime.UtcNow;
if (current - _lastActivityTime < _gcAfterTimeSpan)
{
// we are having activities.
return;
}
using (Logger.LogBlock(FunctionId.AssetStorage_ForceGC, CancellationToken.None))
{
// we didn't have activity for 5 min. spend some time to drop
// unused memory
for (var i = 0; i < 3; i++)
{
GC.Collect();
}
}
// update gc run time
_lastGCRun = current;
}
private void CleanAssets()
{
if (_assets.Count == 0)
{
// no asset, nothing to do.
return;
}
var current = DateTime.UtcNow;
using (Logger.LogBlock(FunctionId.AssetStorage_CleanAssets, CancellationToken.None))
{
foreach (var kvp in _assets.ToArray())
......
// 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.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
......@@ -53,18 +54,26 @@ public Task CalculateDiagnosticsAsync(DiagnosticArguments arguments, string stre
}, cancellationToken);
}
private async Task SerializeDiagnosticResultAsync(string streamName, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
private async Task<int> SerializeDiagnosticResultAsync(string streamName, DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result, CancellationToken cancellationToken)
{
var count = 0;
using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_SerializeDiagnosticResultAsync, GetResultLogInfo, result, cancellationToken))
using (var stream = await DirectStream.GetAsync(streamName, cancellationToken).ConfigureAwait(false))
{
using (var writer = new ObjectWriter(stream))
{
DiagnosticResultSerializer.Serialize(writer, result, cancellationToken);
var info = DiagnosticResultSerializer.Serialize(writer, result, cancellationToken);
// save log for debugging
Log(TraceEventType.Information, $"diagnostics: {info.diagnostics}, telemetry: {info.telemetry}, exceptions: {info.exceptions}");
}
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
return count;
}
private static string GetResultLogInfo(DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder> result)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册