Merge pull request #2653 from dotnet/piotrpMSFT/issue2584/multicoreJIT
Piotrp msft/issue2584/multicore jit
This commit is contained in:
commit
69a32cc010
14 changed files with 386 additions and 47 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,15 @@ namespace Microsoft.DotNet.Tools.Common
|
||||||
public static void EnsureParentDirectory(string filePath)
|
public static void EnsureParentDirectory(string filePath)
|
||||||
{
|
{
|
||||||
string directory = Path.GetDirectoryName(filePath);
|
string directory = Path.GetDirectoryName(filePath);
|
||||||
if (!Directory.Exists(directory))
|
|
||||||
|
EnsureDirectory(directory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureDirectory(string directoryPath)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(directoryPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directoryPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,14 +93,26 @@ namespace Microsoft.DotNet.TestFramework
|
||||||
throw new Exception($"Cannot find '{testProjectName}' at '{AssetsRoot}'");
|
throw new Exception($"Cannot find '{testProjectName}' at '{AssetsRoot}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var testDestination = GetTestDestinationDirectoryPath(testProjectName, callingMethod, identifier);
|
||||||
|
var testInstance = new TestInstance(testProjectDir, testDestination);
|
||||||
|
return testInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestDirectory CreateTestDirectory([CallerMemberName] string callingMethod = "", string identifier = "")
|
||||||
|
{
|
||||||
|
var testDestination = GetTestDestinationDirectoryPath(string.Empty, callingMethod, identifier);
|
||||||
|
|
||||||
|
return new TestDirectory(testDestination);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTestDestinationDirectoryPath(string testProjectName, string callingMethod, string identifier)
|
||||||
|
{
|
||||||
#if NET451
|
#if NET451
|
||||||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
#else
|
#else
|
||||||
string baseDirectory = AppContext.BaseDirectory;
|
string baseDirectory = AppContext.BaseDirectory;
|
||||||
#endif
|
#endif
|
||||||
string testDestination = Path.Combine(baseDirectory, callingMethod + identifier, testProjectName);
|
return Path.Combine(baseDirectory, callingMethod + identifier, testProjectName);
|
||||||
var testInstance = new TestInstance(testProjectDir, testDestination);
|
|
||||||
return testInstance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
38
src/Microsoft.DotNet.TestFramework/TestDirectory.cs
Normal file
38
src/Microsoft.DotNet.TestFramework/TestDirectory.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.TestFramework
|
||||||
|
{
|
||||||
|
public class TestDirectory
|
||||||
|
{
|
||||||
|
internal TestDirectory(string path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(nameof(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
Path = path;
|
||||||
|
|
||||||
|
EnsureExistsAndEmpty(Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Path { get; private set; }
|
||||||
|
|
||||||
|
private static void EnsureExistsAndEmpty(string path)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.Delete(path, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,36 +9,22 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.TestFramework
|
namespace Microsoft.DotNet.TestFramework
|
||||||
{
|
{
|
||||||
public class TestInstance
|
public class TestInstance: TestDirectory
|
||||||
{
|
{
|
||||||
// made tolower because the rest of the class works with normalized tolower strings
|
// made tolower because the rest of the class works with normalized tolower strings
|
||||||
private static readonly IEnumerable<string> BuildArtifactBlackList = new List<string>() {".IncrementalCache", ".SDKVersion"}.Select(s => s.ToLower()).ToArray();
|
private static readonly IEnumerable<string> BuildArtifactBlackList = new List<string>() {".IncrementalCache", ".SDKVersion"}.Select(s => s.ToLower()).ToArray();
|
||||||
|
|
||||||
private string _testDestination;
|
|
||||||
private string _testAssetRoot;
|
private string _testAssetRoot;
|
||||||
|
|
||||||
internal TestInstance(string testAssetRoot, string testDestination)
|
internal TestInstance(string testAssetRoot, string testDestination) : base(testDestination)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Copying {testAssetRoot} to {testDestination}");
|
|
||||||
if (string.IsNullOrEmpty(testAssetRoot))
|
if (string.IsNullOrEmpty(testAssetRoot))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("testScenario");
|
throw new ArgumentException("testAssetRoot");
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(testDestination))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("testDestination");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_testAssetRoot = testAssetRoot;
|
_testAssetRoot = testAssetRoot;
|
||||||
_testDestination = testDestination;
|
|
||||||
|
|
||||||
if (Directory.Exists(testDestination))
|
|
||||||
{
|
|
||||||
Directory.Delete(testDestination, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory.CreateDirectory(testDestination);
|
|
||||||
CopySource();
|
CopySource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,15 +34,15 @@ namespace Microsoft.DotNet.TestFramework
|
||||||
.Where(dir =>
|
.Where(dir =>
|
||||||
{
|
{
|
||||||
dir = dir.ToLower();
|
dir = dir.ToLower();
|
||||||
return !dir.EndsWith($"{Path.DirectorySeparatorChar}bin")
|
return !dir.EndsWith($"{System.IO.Path.DirectorySeparatorChar}bin")
|
||||||
&& !dir.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
|
&& !dir.Contains($"{System.IO.Path.DirectorySeparatorChar}bin{System.IO.Path.DirectorySeparatorChar}")
|
||||||
&& !dir.EndsWith($"{Path.DirectorySeparatorChar}obj")
|
&& !dir.EndsWith($"{System.IO.Path.DirectorySeparatorChar}obj")
|
||||||
&& !dir.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
|
&& !dir.Contains($"{System.IO.Path.DirectorySeparatorChar}obj{System.IO.Path.DirectorySeparatorChar}");
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (string sourceDir in sourceDirs)
|
foreach (string sourceDir in sourceDirs)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(sourceDir.Replace(_testAssetRoot, _testDestination));
|
Directory.CreateDirectory(sourceDir.Replace(_testAssetRoot, Path));
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceFiles = Directory.GetFiles(_testAssetRoot, "*.*", SearchOption.AllDirectories)
|
var sourceFiles = Directory.GetFiles(_testAssetRoot, "*.*", SearchOption.AllDirectories)
|
||||||
|
@ -64,13 +50,13 @@ namespace Microsoft.DotNet.TestFramework
|
||||||
{
|
{
|
||||||
file = file.ToLower();
|
file = file.ToLower();
|
||||||
return !file.EndsWith("project.lock.json")
|
return !file.EndsWith("project.lock.json")
|
||||||
&& !file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
|
&& !file.Contains($"{System.IO.Path.DirectorySeparatorChar}bin{System.IO.Path.DirectorySeparatorChar}")
|
||||||
&& !file.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
|
&& !file.Contains($"{System.IO.Path.DirectorySeparatorChar}obj{System.IO.Path.DirectorySeparatorChar}");
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (string srcFile in sourceFiles)
|
foreach (string srcFile in sourceFiles)
|
||||||
{
|
{
|
||||||
string destFile = srcFile.Replace(_testAssetRoot, _testDestination);
|
string destFile = srcFile.Replace(_testAssetRoot, Path);
|
||||||
File.Copy(srcFile, destFile, true);
|
File.Copy(srcFile, destFile, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +65,7 @@ namespace Microsoft.DotNet.TestFramework
|
||||||
{
|
{
|
||||||
foreach (string lockFile in Directory.GetFiles(_testAssetRoot, "project.lock.json", SearchOption.AllDirectories))
|
foreach (string lockFile in Directory.GetFiles(_testAssetRoot, "project.lock.json", SearchOption.AllDirectories))
|
||||||
{
|
{
|
||||||
string destinationLockFile = lockFile.Replace(_testAssetRoot, _testDestination);
|
string destinationLockFile = lockFile.Replace(_testAssetRoot, Path);
|
||||||
File.Copy(lockFile, destinationLockFile, true);
|
File.Copy(lockFile, destinationLockFile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,15 +78,15 @@ namespace Microsoft.DotNet.TestFramework
|
||||||
.Where(dir =>
|
.Where(dir =>
|
||||||
{
|
{
|
||||||
dir = dir.ToLower();
|
dir = dir.ToLower();
|
||||||
return dir.EndsWith($"{Path.DirectorySeparatorChar}bin")
|
return dir.EndsWith($"{System.IO.Path.DirectorySeparatorChar}bin")
|
||||||
|| dir.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
|
|| dir.Contains($"{System.IO.Path.DirectorySeparatorChar}bin{System.IO.Path.DirectorySeparatorChar}")
|
||||||
|| dir.EndsWith($"{Path.DirectorySeparatorChar}obj")
|
|| dir.EndsWith($"{System.IO.Path.DirectorySeparatorChar}obj")
|
||||||
|| dir.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
|
|| dir.Contains($"{System.IO.Path.DirectorySeparatorChar}obj{System.IO.Path.DirectorySeparatorChar}");
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (string dirPath in binDirs)
|
foreach (string dirPath in binDirs)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(dirPath.Replace(_testAssetRoot, _testDestination));
|
Directory.CreateDirectory(dirPath.Replace(_testAssetRoot, Path));
|
||||||
}
|
}
|
||||||
|
|
||||||
var binFiles = Directory.GetFiles(_testAssetRoot, "*.*", SearchOption.AllDirectories)
|
var binFiles = Directory.GetFiles(_testAssetRoot, "*.*", SearchOption.AllDirectories)
|
||||||
|
@ -108,26 +94,23 @@ namespace Microsoft.DotNet.TestFramework
|
||||||
{
|
{
|
||||||
file = file.ToLower();
|
file = file.ToLower();
|
||||||
|
|
||||||
var isArtifact = file.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")
|
var isArtifact = file.Contains($"{System.IO.Path.DirectorySeparatorChar}bin{System.IO.Path.DirectorySeparatorChar}")
|
||||||
|| file.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}");
|
|| file.Contains($"{System.IO.Path.DirectorySeparatorChar}obj{System.IO.Path.DirectorySeparatorChar}");
|
||||||
|
|
||||||
var isBlackListed = BuildArtifactBlackList.Any(b => file.Contains(b));
|
var isBlackListed = BuildArtifactBlackList.Any(b => file.Contains(b));
|
||||||
|
|
||||||
return isArtifact && !isBlackListed;
|
return isArtifact && !isBlackListed;
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (string binFile in binFiles)
|
foreach (string binFile in binFiles)
|
||||||
{
|
{
|
||||||
string destFile = binFile.Replace(_testAssetRoot, _testDestination);
|
string destFile = binFile.Replace(_testAssetRoot, Path);
|
||||||
File.Copy(binFile, destFile, true);
|
File.Copy(binFile, destFile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string TestRoot
|
public string TestRoot => Path;
|
||||||
{
|
|
||||||
get { return _testDestination; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
63
src/dotnet/MulticoreJitActivator.cs
Normal file
63
src/dotnet/MulticoreJitActivator.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// 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 Env.GetEnvironmentVariableAsBool("DOTNET_DISABLE_MULTICOREJIT");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartCliProfileOptimization()
|
||||||
|
{
|
||||||
|
var profileOptimizationRootPath = new MulticoreJitProfilePathCalculator().MulticoreJitProfilePath;
|
||||||
|
|
||||||
|
if (!TryEnsureDirectory(profileOptimizationRootPath))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssemblyLoadContext.Default.SetProfileOptimizationRoot(profileOptimizationRootPath);
|
||||||
|
|
||||||
|
AssemblyLoadContext.Default.StartProfileOptimization("dotnet");
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryEnsureDirectory(string directoryPath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PathUtility.EnsureDirectory(directoryPath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
src/dotnet/MulticoreJitProfilePathCalculator.cs
Normal file
57
src/dotnet/MulticoreJitProfilePathCalculator.cs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// 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.InteropServices;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Cli
|
||||||
|
{
|
||||||
|
internal class MulticoreJitProfilePathCalculator
|
||||||
|
{
|
||||||
|
private string _multicoreJitProfilePath;
|
||||||
|
|
||||||
|
public string MulticoreJitProfilePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_multicoreJitProfilePath == null)
|
||||||
|
{
|
||||||
|
CalculateProfileRootPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _multicoreJitProfilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalculateProfileRootPath()
|
||||||
|
{
|
||||||
|
var profileRoot = GetRuntimeDataRootPathString();
|
||||||
|
|
||||||
|
var version = Product.Version;
|
||||||
|
|
||||||
|
var rid = PlatformServices.Default.Runtime.GetRuntimeIdentifier();
|
||||||
|
|
||||||
|
_multicoreJitProfilePath = Path.Combine(profileRoot, "sdk", version, rid, "optimizationdata");
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRuntimeDataRootPathString()
|
||||||
|
{
|
||||||
|
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? GetWindowsRuntimeDataRoot()
|
||||||
|
: GetNonWindowsRuntimeDataRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetWindowsRuntimeDataRoot()
|
||||||
|
{
|
||||||
|
return $@"{(Environment.GetEnvironmentVariable("LocalAppData"))}\Microsoft\dotnet\";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetNonWindowsRuntimeDataRoot()
|
||||||
|
{
|
||||||
|
return $"{(Environment.GetEnvironmentVariable("HOME"))}/.dotnet/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.Loader;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.DotNet.Cli.Utils;
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
using Microsoft.DotNet.InternalAbstractions;
|
using Microsoft.DotNet.InternalAbstractions;
|
||||||
|
@ -42,6 +43,8 @@ namespace Microsoft.DotNet.Cli
|
||||||
{
|
{
|
||||||
DebugHelper.HandleDebugSwitch(ref args);
|
DebugHelper.HandleDebugSwitch(ref args);
|
||||||
|
|
||||||
|
new MulticoreJitActivator().TryActivateMulticoreJit();
|
||||||
|
|
||||||
if (Env.GetEnvironmentVariableAsBool("DOTNET_CLI_CAPTURE_TIMING", false))
|
if (Env.GetEnvironmentVariableAsBool("DOTNET_CLI_CAPTURE_TIMING", false))
|
||||||
{
|
{
|
||||||
PerfTrace.Enabled = true;
|
PerfTrace.Enabled = true;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// 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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
|
@ -193,5 +193,12 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
|
||||||
process.Start();
|
process.Start();
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TestCommand WithEnvironmentVariable(string name, string value)
|
||||||
|
{
|
||||||
|
Environment.Add(name, value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests
|
||||||
{
|
{
|
||||||
Test(new string[] { }, new[] { "L21" }, workingDirectory: Path.Combine("src", "L21"));
|
Test(new string[] { }, new[] { "L21" }, workingDirectory: Path.Combine("src", "L21"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void TestFailsIfNoProjectJsonInCurrentDirectoryWithNoArguments()
|
public void TestFailsIfNoProjectJsonInCurrentDirectoryWithNoArguments()
|
||||||
{
|
{
|
||||||
|
|
131
test/dotnet.Tests/GivenThatIWantToManageMulticoreJIT.cs
Normal file
131
test/dotnet.Tests/GivenThatIWantToManageMulticoreJIT.cs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
// 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.TestFramework;
|
||||||
|
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 class GivenThatIWantToManageMulticoreJIT : TestBase
|
||||||
|
{
|
||||||
|
ITestOutputHelper _output;
|
||||||
|
private const string OptimizationProfileFileName = "dotnet";
|
||||||
|
|
||||||
|
public GivenThatIWantToManageMulticoreJIT(ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
_output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void When_invoked_then_dotnet_writes_optimization_data_to_the_profile_root()
|
||||||
|
{
|
||||||
|
var testDirectory = TestAssetsManager.CreateTestDirectory();
|
||||||
|
var testStartTime = GetTruncatedDateTime();
|
||||||
|
|
||||||
|
new TestCommand("dotnet")
|
||||||
|
.WithUserProfileRoot(testDirectory.Path)
|
||||||
|
.ExecuteWithCapturedOutput("--help");
|
||||||
|
|
||||||
|
var optimizationProfileFilePath = GetOptimizationProfileFilePath(testDirectory.Path);
|
||||||
|
|
||||||
|
File.Exists(optimizationProfileFilePath)
|
||||||
|
.Should().BeTrue("Because dotnet CLI creates it after each run");
|
||||||
|
|
||||||
|
File.GetLastWriteTimeUtc(optimizationProfileFilePath)
|
||||||
|
.Should().BeOnOrAfter(testStartTime, "Because dotnet CLI was executed after that time");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void When_invoked_with_MulticoreJit_disabled_then_dotnet_does_not_writes_optimization_data_to_the_profile_root()
|
||||||
|
{
|
||||||
|
var testDirectory = TestAssetsManager.CreateTestDirectory();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
var rid = PlatformServices.Default.Runtime.GetRuntimeIdentifier();
|
||||||
|
|
||||||
|
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||||
|
? $@"Microsoft\dotnet\sdk\{version}\{rid}\optimizationdata"
|
||||||
|
: $@".dotnet/sdk/{version}/{rid}/optimizationdata";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDotnetVersion()
|
||||||
|
{
|
||||||
|
return Command.Create("dotnet", new[] { "--version" })
|
||||||
|
.CaptureStdOut()
|
||||||
|
.Execute()
|
||||||
|
.StdOut
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
test/dotnet.Tests/TestCommandExtensions.cs
Normal file
31
test/dotnet.Tests/TestCommandExtensions.cs
Normal 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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
"target": "project",
|
"target": "project",
|
||||||
"type": "build"
|
"type": "build"
|
||||||
},
|
},
|
||||||
|
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20581",
|
||||||
"xunit": "2.1.0",
|
"xunit": "2.1.0",
|
||||||
"dotnet-test-xunit": "1.0.0-rc2-173361-36"
|
"dotnet-test-xunit": "1.0.0-rc2-173361-36"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue