From 0c119c1a64c177f7be20a1621d40cfdd58bdcb8a Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 18 Jun 2019 12:40:04 -0700 Subject: [PATCH 1/3] Clean up the use of 'SetProfileRoot' and 'StartProfile' in ConsoleHost --- build.psm1 | 1 + .../host/msh/CommandLineParameterParser.cs | 17 +---------- .../host/msh/ConsoleHost.cs | 24 ++++++++-------- .../host/msh/ManagedEntrance.cs | 2 +- .../CoreCLR/CorePsAssemblyLoadContext.cs | 16 ----------- .../engine/InitialSessionState.cs | 6 ++-- .../utils/ClrFacade.cs | 18 ------------ tools/performance/GC.Regions.xml | 5 ++-- tools/performance/Invoke-PerfviewPS.ps1 | 28 ++++--------------- tools/performance/PowerShell.Regions.xml | 1 + tools/performance/PowerShell.stacktags | 9 +++--- 11 files changed, 33 insertions(+), 94 deletions(-) diff --git a/build.psm1 b/build.psm1 index 9f83cb3a4bf..1b4559af3f6 100644 --- a/build.psm1 +++ b/build.psm1 @@ -2154,6 +2154,7 @@ function Start-CrossGen { # Common PowerShell libraries to crossgen $psCoreAssemblyList = @( + "pwsh.dll", "Microsoft.PowerShell.Commands.Utility.dll", "Microsoft.PowerShell.Commands.Management.dll", "Microsoft.PowerShell.Security.dll", diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs index eb46b6a7e6e..4791100c68b 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs @@ -498,21 +498,6 @@ private static bool TryParseSettingFileHelper(string[] args, int settingFileArgI return true; } - /// - /// Processes the command line parameters to ConsoleHost which must be parsed before the Host is created. - /// Success to indicate that the program should continue running. - /// - /// - /// The command line parameters to be processed. - /// - internal static void EarlyParse(string[] args) - { - // indicates that we've called this method on this instance, and that when it's done, the state variables - // will reflect the parse. - - EarlyParseHelper(args); - } - private static string GetConfigurationNameFromGroupPolicy() { // Current user policy takes precedence. @@ -529,7 +514,7 @@ private static string GetConfigurationNameFromGroupPolicy() /// /// The command line parameters to be processed. /// - private static void EarlyParseHelper(string[] args) + internal static void EarlyParse(string[] args) { if (args == null) { diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index a0689ba60a3..96832702367 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -20,6 +20,7 @@ using System.Management.Automation.Remoting; using System.Management.Automation.Security; using System.Threading; +using System.Runtime; using System.Runtime.InteropServices; using System.Management.Automation.Language; @@ -133,7 +134,7 @@ internal static int Start( Directory.CreateDirectory(profileDir); } #endif - ClrFacade.SetProfileOptimizationRoot(profileDir); + ProfileOptimization.SetProfileRoot(profileDir); } catch { @@ -143,7 +144,7 @@ internal static int Start( uint exitCode = ExitCodeSuccess; - System.Threading.Thread.CurrentThread.Name = "ConsoleHost main thread"; + Thread.CurrentThread.Name = "ConsoleHost main thread"; try { @@ -205,26 +206,26 @@ internal static int Start( // First check for and handle PowerShell running in a server mode. if (s_cpp.ServerMode) { - ClrFacade.StartProfileOptimization("StartupProfileData-ServerMode"); + ProfileOptimization.StartProfile("StartupProfileData-ServerMode"); System.Management.Automation.Remoting.Server.OutOfProcessMediator.Run(s_cpp.InitialCommand); exitCode = 0; } else if (s_cpp.NamedPipeServerMode) { - ClrFacade.StartProfileOptimization("StartupProfileData-NamedPipeServerMode"); + ProfileOptimization.StartProfile("StartupProfileData-NamedPipeServerMode"); System.Management.Automation.Remoting.RemoteSessionNamedPipeServer.RunServerMode( s_cpp.ConfigurationName); exitCode = 0; } else if (s_cpp.SSHServerMode) { - ClrFacade.StartProfileOptimization("StartupProfileData-SSHServerMode"); + ProfileOptimization.StartProfile("StartupProfileData-SSHServerMode"); System.Management.Automation.Remoting.Server.SSHProcessMediator.Run(s_cpp.InitialCommand); exitCode = 0; } else if (s_cpp.SocketServerMode) { - ClrFacade.StartProfileOptimization("StartupProfileData-SocketServerMode"); + ProfileOptimization.StartProfile("StartupProfileData-SocketServerMode"); System.Management.Automation.Remoting.Server.HyperVSocketMediator.Run(s_cpp.InitialCommand, s_cpp.ConfigurationName); exitCode = 0; @@ -238,16 +239,17 @@ internal static int Start( throw hostException; } + ProfileOptimization.StartProfile( + s_theConsoleHost.LoadPSReadline() + ? "StartupProfileData-Interactive" + : "StartupProfileData-NonInteractive"); + s_theConsoleHost.BindBreakHandler(); PSHost.IsStdOutputRedirected = Console.IsOutputRedirected; // Send startup telemetry for ConsoleHost startup ApplicationInsightsTelemetry.SendPSCoreStartupTelemetry(); - ClrFacade.StartProfileOptimization( - s_theConsoleHost.LoadPSReadline() - ? "StartupProfileData-Interactive" - : "StartupProfileData-NonInteractive"); exitCode = s_theConsoleHost.Run(s_cpp, false); } } @@ -2833,7 +2835,7 @@ private class ConsoleHostStartupException : Exception private ConsoleControl.ConsoleModes _savedConsoleMode = ConsoleControl.ConsoleModes.Unknown; private ConsoleControl.ConsoleModes _initialConsoleMode = ConsoleControl.ConsoleModes.Unknown; #endif - private System.Threading.Thread _breakHandlerThread; + private Thread _breakHandlerThread; private bool _isDisposed; internal ConsoleHostUserInterface ui; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs index b400f7ed0f4..fec51340e6b 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs @@ -31,9 +31,9 @@ public sealed class UnmanagedPSEntry public static int Start(string consoleFilePath, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)]string[] args, int argc) #pragma warning restore 1573 { + System.Management.Automation.Runspaces.EarlyStartup.Init(); // We need to read the settings file before we create the console host Microsoft.PowerShell.CommandLineParameterParser.EarlyParse(args); - System.Management.Automation.Runspaces.EarlyStartup.Init(); #if !UNIX // NOTE: On Unix, logging has to be deferred until after command-line parsing diff --git a/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs b/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs index d1687ff6ab1..3d55ed1b674 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsAssemblyLoadContext.cs @@ -194,22 +194,6 @@ internal IEnumerable GetAssembly(string namespaceQualifiedTypeName) return null; } - /// - /// Set the profile optimization root on the appropriate load context. - /// - internal void SetProfileOptimizationRootImpl(string directoryPath) - { - AssemblyLoadContext.Default.SetProfileOptimizationRoot(directoryPath); - } - - /// - /// Start the profile optimization on the appropriate load context. - /// - internal void StartProfileOptimizationImpl(string profile) - { - AssemblyLoadContext.Default.StartProfileOptimization(profile); - } - #endregion Internal_Methods #region Private_Methods diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs index 18bfdf3bd0b..2ae67654896 100644 --- a/src/System.Management.Automation/engine/InitialSessionState.cs +++ b/src/System.Management.Automation/engine/InitialSessionState.cs @@ -56,13 +56,13 @@ internal static void Init() { // Loading the resources for System.Management.Automation can be expensive, so force that to // happen early on a background thread. - var unused0 = RunspaceInit.OutputEncodingDescription; + _ = RunspaceInit.OutputEncodingDescription; // This will init some tables and could load some assemblies. - var unused1 = TypeAccelerators.builtinTypeAccelerators; + _ = TypeAccelerators.builtinTypeAccelerators; // This will init some tables and could load some assemblies. - var unused2 = LanguagePrimitives.GetEnumerator(null); + LanguagePrimitives.GetEnumerator(null); }); } } diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs index eea0ffb7d70..9feafe40d4d 100644 --- a/src/System.Management.Automation/utils/ClrFacade.cs +++ b/src/System.Management.Automation/utils/ClrFacade.cs @@ -361,24 +361,6 @@ internal static string ToDmtfDateTime(DateTime date) #endif } - /// - /// Facade for ProfileOptimization.SetProfileRoot. - /// - /// The full path to the folder where profile files are stored for the current application domain. - internal static void SetProfileOptimizationRoot(string directoryPath) - { - PSAssemblyLoadContext.SetProfileOptimizationRootImpl(directoryPath); - } - - /// - /// Facade for ProfileOptimization.StartProfile. - /// - /// The file name of the profile to use. - internal static void StartProfileOptimization(string profile) - { - PSAssemblyLoadContext.StartProfileOptimizationImpl(profile); - } - #endregion Misc /// diff --git a/tools/performance/GC.Regions.xml b/tools/performance/GC.Regions.xml index b89be6ffd7c..5b5de4c816d 100644 --- a/tools/performance/GC.Regions.xml +++ b/tools/performance/GC.Regions.xml @@ -1,12 +1,13 @@ + diff --git a/tools/performance/Invoke-PerfviewPS.ps1 b/tools/performance/Invoke-PerfviewPS.ps1 index 77a33f3a754..66ece758972 100644 --- a/tools/performance/Invoke-PerfviewPS.ps1 +++ b/tools/performance/Invoke-PerfviewPS.ps1 @@ -8,8 +8,9 @@ param( $ScriptBlock, $LogFileName = '.\perfview.log', - - $PowerShellPath = $(Get-Command pwsh.exe).Source) + $PowerShellPath = $(Get-Command pwsh.exe).Source, + $PerfViewPath = $(Get-Command PerfView.exe).Source +) $EncodedScriptBlock = [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($ScriptBlock.ToString())) $perfViewArgs = @( @@ -30,26 +31,7 @@ $perfViewArgs = @( $EncodedScriptBlock ) -$process = Start-Process -FilePath (Get-Command PerfView.exe).Source -ArgumentList $perfViewArgs -PassThru - -$rs = [runspacefactory]::CreateRunspace($host) -$rs.Open() -$ps = [powershell]::Create() -$ps.Runspace = $rs - -$null = $ps.AddCommand("Get-Content"). - AddArgument($LogFileName). - AddParameter("Wait"). - AddParameter("Tail", 0) -$null = $ps.AddCommand("Out-Host") - -# If log file doesn't exist yet, wait a little bit so Get-Content doesn't fail -while (!(Test-Path $LogFileName)) -{ - Start-Sleep -Seconds 1 -} - -$null = $ps.BeginInvoke() +$process = Start-Process -FilePath $PerfViewPath -ArgumentList $perfViewArgs -PassThru $process.WaitForExit() -$ps.Stop() +Get-Content $LogFileName | Out-Host diff --git a/tools/performance/PowerShell.Regions.xml b/tools/performance/PowerShell.Regions.xml index 0a070242487..180374ecf5c 100644 --- a/tools/performance/PowerShell.Regions.xml +++ b/tools/performance/PowerShell.Regions.xml @@ -1,5 +1,6 @@ + diff --git a/tools/performance/PowerShell.stacktags b/tools/performance/PowerShell.stacktags index a4bbecfc949..ed1b89e9a9a 100644 --- a/tools/performance/PowerShell.stacktags +++ b/tools/performance/PowerShell.stacktags @@ -1,15 +1,16 @@ + - - + + - - + + From b842fe4ff95c00061ca1c32b6c1f813a24cb6379 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 18 Jun 2019 14:08:32 -0700 Subject: [PATCH 2/3] Remove 'pwsh.pdb' from our component file list --- assets/files.wxs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/assets/files.wxs b/assets/files.wxs index d19c2b8bb97..d1651ac5a8a 100644 --- a/assets/files.wxs +++ b/assets/files.wxs @@ -325,9 +325,6 @@ - - - @@ -2456,7 +2453,6 @@ - From 6a03be6e2d5e320a9702d8b55d346e0f98db2a8a Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Tue, 18 Jun 2019 22:20:33 -0700 Subject: [PATCH 3/3] Address Ilya's comments --- .../host/msh/ManagedEntrance.cs | 5 +++-- tools/performance/Invoke-PerfviewPS.ps1 | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs index fec51340e6b..eb9b588d414 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ManagedEntrance.cs @@ -27,11 +27,12 @@ public sealed class UnmanagedPSEntry /// /// Command line arguments to the managed MSH /// -#pragma warning disable 1573 + /// public static int Start(string consoleFilePath, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)]string[] args, int argc) -#pragma warning restore 1573 { + // Warm up some components concurrently on background threads. System.Management.Automation.Runspaces.EarlyStartup.Init(); + // We need to read the settings file before we create the console host Microsoft.PowerShell.CommandLineParameterParser.EarlyParse(args); diff --git a/tools/performance/Invoke-PerfviewPS.ps1 b/tools/performance/Invoke-PerfviewPS.ps1 index 66ece758972..99ff988da29 100644 --- a/tools/performance/Invoke-PerfviewPS.ps1 +++ b/tools/performance/Invoke-PerfviewPS.ps1 @@ -8,8 +8,8 @@ param( $ScriptBlock, $LogFileName = '.\perfview.log', - $PowerShellPath = $(Get-Command pwsh.exe).Source, - $PerfViewPath = $(Get-Command PerfView.exe).Source + $PowerShellPath = $(Get-Command -Name pwsh.exe).Source, + $PerfViewPath = $(Get-Command -Name PerfView.exe).Source ) $EncodedScriptBlock = [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($ScriptBlock.ToString()))