mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Improve formatting performance by having better primitives on PSObject (#8785)
By not doing excessive amounts of extra work, formatting can be sped up quite significantly (about 8x faster). The main change comes from adding new, more efficient, primitive to query an object for the existence of an instance member. The formatting system has been checking for if an object has properties other than some decorated properties added by PS remoting, and it doesn't this by retrieving all properties which results in heavy allocations and wasted cycles. By adding `GetFirstOrDefault` to `PSObject` and similar primitives to the underlying Adapters, we are able to return early, without having to get all properties back.
This commit is contained in:
committed by
Dongbo Wang
parent
95a8091991
commit
42c289fc8e
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Management.Automation.Language;
|
||||
using Xunit;
|
||||
|
||||
namespace PSTests.Parallel
|
||||
{
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Xml;
|
||||
|
||||
using Microsoft.Management.Infrastructure;
|
||||
|
||||
public static class PSObjectTests
|
||||
{
|
||||
[Fact]
|
||||
public static void TestEmptyObjectHasNoProperty()
|
||||
{
|
||||
var psObject = new PSObject();
|
||||
var actual = psObject.GetFirstPropertyOrDefault(name => true);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TestWrappedDateTimeHasReflectedMember()
|
||||
{
|
||||
var psObject = new PSObject(DateTime.Now);
|
||||
var member = psObject.GetFirstPropertyOrDefault(name => name == "DayOfWeek");
|
||||
Assert.NotNull(member);
|
||||
Assert.Equal("DayOfWeek", member.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TestAdaptedMember()
|
||||
{
|
||||
var psObject = new PSObject(DateTime.Now);
|
||||
psObject.Members.Add(new PSNoteProperty("NewMember", "AValue"));
|
||||
var member = psObject.GetFirstPropertyOrDefault(name => name == "NewMember");
|
||||
Assert.NotNull(member);
|
||||
Assert.Equal("NewMember", member.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TestShadowedMember()
|
||||
{
|
||||
var psObject = new PSObject(DateTime.Now);
|
||||
psObject.Members.Add(new PSNoteProperty("DayOfWeek", "AValue"));
|
||||
var member = psObject.GetFirstPropertyOrDefault(name => name == "DayOfWeek");
|
||||
Assert.NotNull(member);
|
||||
Assert.Equal("DayOfWeek", member.Name);
|
||||
Assert.Equal("AValue", member.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TestMemberSetIsNotProperty()
|
||||
{
|
||||
var psObject = new PSObject(DateTime.Now);
|
||||
var psNoteProperty = new PSNoteProperty("NewMember", "AValue");
|
||||
psObject.Members.Add(psNoteProperty);
|
||||
psObject.Members.Add(new PSMemberSet("NewMemberSet", new[] { psNoteProperty }));
|
||||
|
||||
var member = psObject.GetFirstPropertyOrDefault(name => name == "NewMemberSet");
|
||||
Assert.Null(member);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TestMemberSet()
|
||||
{
|
||||
var psObject = new PSObject(DateTime.Now);
|
||||
var psNoteProperty = new PSNoteProperty("NewMember", "AValue");
|
||||
psObject.Members.Add(psNoteProperty);
|
||||
psObject.Members.Add(new PSMemberSet("NewMemberSet", new[] { psNoteProperty }));
|
||||
|
||||
var member = psObject.Members.FirstOrDefault(name => name == "NewMemberSet");
|
||||
Assert.NotNull(member);
|
||||
Assert.Equal("NewMemberSet", member.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TextXmlElementMember()
|
||||
{
|
||||
var doc = new XmlDocument();
|
||||
var root = doc.CreateElement("root");
|
||||
doc.AppendChild(root);
|
||||
var firstChild = doc.CreateElement("elem1");
|
||||
root.AppendChild(firstChild);
|
||||
root.InsertAfter(doc.CreateElement("elem2"), firstChild);
|
||||
|
||||
var psObject = new PSObject(root);
|
||||
var member = psObject.GetFirstPropertyOrDefault(name => name.StartsWith("elem"));
|
||||
Assert.Equal("elem1", member.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public static void TextXmlAttributeMember()
|
||||
{
|
||||
var doc = new XmlDocument();
|
||||
var root = doc.CreateElement("root");
|
||||
doc.AppendChild(root);
|
||||
root.SetAttribute("attr", "value");
|
||||
root.AppendChild(doc.CreateElement("elem"));
|
||||
|
||||
var psObject = new PSObject(root);
|
||||
var member = psObject.GetFirstPropertyOrDefault(name => name.StartsWith("attr"));
|
||||
Assert.Equal("attr", member.Name);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public static void TestCimInstanceProperty()
|
||||
{
|
||||
Skip.IfNot(Platform.IsWindows);
|
||||
var iss = InitialSessionState.CreateDefault2();
|
||||
iss.Commands.Add(new SessionStateCmdletEntry("Get-CimInstance", typeof(Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand), null));
|
||||
using (var ps = PowerShell.Create(iss))
|
||||
{
|
||||
ps.AddCommand("Get-CimInstance").AddParameter("ClassName", "Win32_BIOS");
|
||||
var res = ps.Invoke().FirstOrDefault();
|
||||
Assert.NotNull(res);
|
||||
var member = res.GetFirstPropertyOrDefault(name => name == "Name");
|
||||
Assert.NotNull(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
|
||||
|
||||
<Import Project="../Test.Common.props"/>
|
||||
<Import Project="../Test.Common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>PowerShell xUnit Tests</Description>
|
||||
@@ -16,9 +16,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj"/>
|
||||
<ProjectReference Include="../../src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj"/>
|
||||
<ProjectReference Include="../../src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj"/>
|
||||
<ProjectReference Include="../../src/Microsoft.PowerShell.SDK/Microsoft.PowerShell.SDK.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.PowerShell.Commands.Diagnostics/Microsoft.PowerShell.Commands.Diagnostics.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.WSMan.Management/Microsoft.WSMan.Management.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.Management.Infrastructure.CimCmdlets/Microsoft.Management.Infrastructure.CimCmdlets.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user