From ae3c26c6f2bd98af1a9400320c70b00754750ca8 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Mon, 1 Oct 2018 15:47:58 -0400 Subject: [PATCH 1/2] Enable command lookup caching by name and filter Add a struct to use as a private struct to use as a key for the command lookup cache. Also re-enable caching in Helper.GetCommandInfo. --- Engine/Helper.cs | 49 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/Engine/Helper.cs b/Engine/Helper.cs index c86e2eb55..89f14c7c1 100644 --- a/Engine/Helper.cs +++ b/Engine/Helper.cs @@ -28,7 +28,7 @@ public class Helper private readonly static Version minSupportedPSVersion = new Version(3, 0); private Dictionary> ruleArguments; private PSVersionTable psVersionTable; - private Dictionary commandInfoCache; + private Dictionary commandInfoCache; #endregion @@ -142,7 +142,7 @@ public void Initialize() ruleArguments = new Dictionary>(StringComparer.OrdinalIgnoreCase); if (commandInfoCache == null) { - commandInfoCache = new Dictionary(StringComparer.OrdinalIgnoreCase); + commandInfoCache = new Dictionary(); } IEnumerable aliases = this.invokeCommand.GetCommands("*", CommandTypes.Alias, true); @@ -700,15 +700,16 @@ public CommandInfo GetCommandInfoLegacy(string name, CommandTypes? commandType = cmdletName = name; } + var key = new CommandLookupKey(name, commandType); lock (getCommandLock) { - if (commandInfoCache.ContainsKey(cmdletName)) + if (commandInfoCache.ContainsKey(key)) { - return commandInfoCache[cmdletName]; + return commandInfoCache[key]; } var commandInfo = GetCommandInfoInternal(cmdletName, commandType); - commandInfoCache.Add(cmdletName, commandInfo); + commandInfoCache.Add(key, commandInfo); return commandInfo; } } @@ -726,15 +727,16 @@ public CommandInfo GetCommandInfo(string name, CommandTypes? commandType = null) return null; } + var key = new CommandLookupKey(name, commandType); lock (getCommandLock) { - if (commandInfoCache.ContainsKey(name)) + if (commandInfoCache.ContainsKey(key)) { - return commandInfoCache[name]; + return commandInfoCache[key]; } var commandInfo = GetCommandInfoInternal(name, commandType); - + commandInfoCache.Add(key, commandInfo); return commandInfo; } } @@ -1910,6 +1912,37 @@ public Version GetPSVersion() } #endregion Methods + + private struct CommandLookupKey : IEquatable + { + private readonly string Name; + + private readonly CommandTypes CommandTypes; + + internal CommandLookupKey(string name, CommandTypes? commandTypes) + { + Name = name; + CommandTypes = commandTypes ?? CommandTypes.All; + } + + public bool Equals(CommandLookupKey other) + { + return CommandTypes == other.CommandTypes + && Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase); + } + + public override int GetHashCode() + { + // Algorithm from https://stackoverflow.com/questions/1646807/quick-and-simple-hash-code-combinations + unchecked + { + int hash = 17; + hash = hash * 31 + Name.ToUpperInvariant().GetHashCode(); + hash = hash * 31 + CommandTypes.GetHashCode(); + return hash; + } + } + } } From 1217068c57056d3848cd8816a211d9357ee2bd75 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Mon, 1 Oct 2018 18:30:38 -0400 Subject: [PATCH 2/2] Moved CommandLookupKey to new file --- Engine/CommandLookupKey.cs | 39 ++++++++++++++++++++++++++++++++++++++ Engine/Helper.cs | 31 ------------------------------ 2 files changed, 39 insertions(+), 31 deletions(-) create mode 100644 Engine/CommandLookupKey.cs diff --git a/Engine/CommandLookupKey.cs b/Engine/CommandLookupKey.cs new file mode 100644 index 000000000..bcd7e7097 --- /dev/null +++ b/Engine/CommandLookupKey.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Management.Automation; + +namespace Microsoft.Windows.PowerShell.ScriptAnalyzer +{ + internal struct CommandLookupKey : IEquatable + { + private readonly string Name; + + private readonly CommandTypes CommandTypes; + + internal CommandLookupKey(string name, CommandTypes? commandTypes) + { + Name = name; + CommandTypes = commandTypes ?? CommandTypes.All; + } + + public bool Equals(CommandLookupKey other) + { + return CommandTypes == other.CommandTypes + && Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase); + } + + public override int GetHashCode() + { + // Algorithm from https://stackoverflow.com/questions/1646807/quick-and-simple-hash-code-combinations + unchecked + { + int hash = 17; + hash = hash * 31 + Name.ToUpperInvariant().GetHashCode(); + hash = hash * 31 + CommandTypes.GetHashCode(); + return hash; + } + } + } +} diff --git a/Engine/Helper.cs b/Engine/Helper.cs index 89f14c7c1..3d1f4a4ad 100644 --- a/Engine/Helper.cs +++ b/Engine/Helper.cs @@ -1912,37 +1912,6 @@ public Version GetPSVersion() } #endregion Methods - - private struct CommandLookupKey : IEquatable - { - private readonly string Name; - - private readonly CommandTypes CommandTypes; - - internal CommandLookupKey(string name, CommandTypes? commandTypes) - { - Name = name; - CommandTypes = commandTypes ?? CommandTypes.All; - } - - public bool Equals(CommandLookupKey other) - { - return CommandTypes == other.CommandTypes - && Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase); - } - - public override int GetHashCode() - { - // Algorithm from https://stackoverflow.com/questions/1646807/quick-and-simple-hash-code-combinations - unchecked - { - int hash = 17; - hash = hash * 31 + Name.ToUpperInvariant().GetHashCode(); - hash = hash * 31 + CommandTypes.GetHashCode(); - return hash; - } - } - } }