Feature Complete

- Add remaining test scenarios
- Refactor implementation
- Add gitignore entry for optimization profiles
This commit is contained in:
Piotr Puszkiewicz 2016-04-22 12:23:26 -07:00 committed by PiotrP
parent 94e620088e
commit 304434433b
5 changed files with 165 additions and 30 deletions

3
.gitignore vendored
View file

@ -3,6 +3,9 @@
# Test results # Test results
*-testResults.xml *-testResults.xml
# Multicore JIT Optimization profiles
**/optimizationdata/dotnet
# NuGet keeps dropping # NuGet keeps dropping
Library/ Library/

View file

@ -0,0 +1,46 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Runtime.Loader;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using Microsoft.Extensions.PlatformAbstractions;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli
{
public class MulticoreJitActivator
{
public bool TryActivateMulticoreJit()
{
var disableMulticoreJit = IsMulticoreJitDisabled();
if (disableMulticoreJit)
{
return false;
}
StartCliProfileOptimization();
return true;
}
private bool IsMulticoreJitDisabled()
{
return Environment.GetEnvironmentVariable("DOTNET_DISABLE_MULTICOREJIT") == "1";
}
private void StartCliProfileOptimization()
{
var profileOptimizationRootPath = new MulticoreJitProfilePathCalculator().MulticoreJitProfilePath;
PathUtility.EnsureDirectory(profileOptimizationRootPath);
AssemblyLoadContext.Default.SetProfileOptimizationRoot(profileOptimizationRootPath);
AssemblyLoadContext.Default.StartProfileOptimization("dotnet");
}
}
}

View file

@ -43,9 +43,7 @@ namespace Microsoft.DotNet.Cli
{ {
DebugHelper.HandleDebugSwitch(ref args); DebugHelper.HandleDebugSwitch(ref args);
AssemblyLoadContext.Default.SetProfileOptimizationRoot( new MulticoreJitActivator().TryActivateMulticoreJit();
new MulticoreJitProfilePathCalculator().MulticoreJitProfilePath);
AssemblyLoadContext.Default.StartProfileOptimization("dotnet");
if (Env.GetEnvironmentVariableAsBool("DOTNET_CLI_CAPTURE_TIMING", false)) if (Env.GetEnvironmentVariableAsBool("DOTNET_CLI_CAPTURE_TIMING", false))
{ {

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.  // Licensed under the MIT license. See LICENSE file in the project root for full license information. 
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.PlatformAbstractions;
using System; using System;
@ -16,52 +17,101 @@ namespace Microsoft.DotNet.Tests
public class GivenThatIWantToManageMulticoreJIT : TestBase public class GivenThatIWantToManageMulticoreJIT : TestBase
{ {
ITestOutputHelper _output; ITestOutputHelper _output;
private const string OptimizationProfileFileName = "dotnet."; private const string OptimizationProfileFileName = "dotnet";
private readonly string _optimizationProfileFilePath;
public GivenThatIWantToManageMulticoreJIT(ITestOutputHelper output) public GivenThatIWantToManageMulticoreJIT(ITestOutputHelper output)
{ {
_output = output; _output = output;
_optimizationProfileFilePath = GetOptimizationProfileFilePath();
} }
[Fact] [Fact]
public void When_invoked_it_writes_optimization_data_to_the_profile_root() public void When_invoked_then_dotnet_writes_optimization_data_to_the_profile_root()
{ {
var testStartTime = DateTime.UtcNow; var testDirectory = TestAssetsManager.CreateTestDirectory();
var testStartTime = GetTruncatedDateTime();
new TestCommand("dotnet") new TestCommand("dotnet")
.Execute("--version"); .WithUserProfileRoot(testDirectory.Path)
.ExecuteWithCapturedOutput("--help");
File.Exists(_optimizationProfileFilePath)
var optimizationProfileFilePath = GetOptimizationProfileFilePath(testDirectory.Path);
File.Exists(optimizationProfileFilePath)
.Should().BeTrue("Because dotnet CLI creates it after each run"); .Should().BeTrue("Because dotnet CLI creates it after each run");
File.GetLastWriteTimeUtc(_optimizationProfileFilePath) File.GetLastWriteTimeUtc(optimizationProfileFilePath)
.Should().BeOnOrAfter(testStartTime, "Because dotnet CLI was executed after that time."); .Should().BeOnOrAfter(testStartTime, "Because dotnet CLI was executed after that time");
} }
private static string GetOptimizationProfileFilePath() [Fact]
public void When_invoked_with_MulticoreJit_disabled_then_dotnet_does_not_writes_optimization_data_to_the_profile_root()
{ {
Console.WriteLine(GetOptimizationRootPath(GetDotnetVersion())); var testDirectory = TestAssetsManager.CreateTestDirectory();
return Path.Combine(GetOptimizationRootPath(GetDotnetVersion()), var testStartTime = GetTruncatedDateTime();
new TestCommand("dotnet")
.WithUserProfileRoot(testDirectory.Path)
.WithEnvironmentVariable("DOTNET_DISABLE_MULTICOREJIT", "1")
.ExecuteWithCapturedOutput("--help");
var optimizationProfileFilePath = GetOptimizationProfileFilePath(testDirectory.Path);
File.Exists(optimizationProfileFilePath)
.Should().BeFalse("Because multicore JIT is disabled");
}
[Fact]
public void When_the_profile_root_is_undefined_then_dotnet_does_not_crash()
{
var testDirectory = TestAssetsManager.CreateTestDirectory();
var testStartTime = GetTruncatedDateTime();
var optimizationProfileFilePath = GetOptimizationProfileFilePath(testDirectory.Path);
new TestCommand("dotnet")
.WithUserProfileRoot("")
.ExecuteWithCapturedOutput("--help")
.Should().Pass();
}
[Fact]
public void When_cli_repo_builds_then_dotnet_writes_optimization_data_to_the_default_profile_root()
{
var optimizationProfileFilePath = GetOptimizationProfileFilePath();
File.Exists(optimizationProfileFilePath)
.Should().BeTrue("Because the dotnet building dotnet writes to the default root");
}
private static string GetOptimizationProfileFilePath(string userHomePath = null)
{
return Path.Combine(
GetUserProfileRoot(userHomePath),
GetOptimizationRootPath(GetDotnetVersion()),
OptimizationProfileFileName); OptimizationProfileFileName);
} }
private static string GetUserProfileRoot(string overrideUserProfileRoot = null)
{
if (overrideUserProfileRoot != null)
{
return overrideUserProfileRoot;
}
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Environment.GetEnvironmentVariable("LocalAppData")
: Environment.GetEnvironmentVariable("HOME");
}
private static string GetOptimizationRootPath(string version) private static string GetOptimizationRootPath(string version)
{ {
var rid = PlatformServices.Default.Runtime.GetRuntimeIdentifier();
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? GetWindowsProfileRoot(version) ? $@"Microsoft\dotnet\sdk\{version}{rid}\optimizationdata"
: GetNonWindowsProfileRoot(version); : $@".dotnet/sdk/{version}/{rid}/optimizationdata";
}
private static string GetWindowsProfileRoot(string version)
{
return $@"{(Environment.GetEnvironmentVariable("LocalAppData"))}\Microsoft\dotnet\sdk\{version}\optimizationdata";
}
private static string GetNonWindowsProfileRoot(string version)
{
return $"{(Environment.GetEnvironmentVariable("HOME"))}/.dotnet/sdk/{version}/optimizationdata";
} }
private static string GetDotnetVersion() private static string GetDotnetVersion()
@ -72,5 +122,12 @@ namespace Microsoft.DotNet.Tests
.StdOut .StdOut
.Trim(); .Trim();
} }
private static DateTime GetTruncatedDateTime()
{
var dt = DateTime.UtcNow;
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0, dt.Kind);
}
} }
} }

View file

@ -0,0 +1,31 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. 
// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Test.Utilities;
using Microsoft.Extensions.PlatformAbstractions;
using System;
using System.IO;
using System.Runtime.InteropServices;
using Xunit;
using Xunit.Abstractions;
using FluentAssertions;
namespace Microsoft.DotNet.Tests
{
public static class TestCommandExtensions
{
public static TestCommand WithUserProfileRoot(this TestCommand testCommand, string path)
{
var userProfileEnvironmentVariableName = GetUserProfileEnvironmentVariableName();
return testCommand.WithEnvironmentVariable(userProfileEnvironmentVariableName, path);
}
private static string GetUserProfileEnvironmentVariableName()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? "LocalAppData"
: "HOME";
}
}
}