Powershell: LINQ in the compiler

Created on 18 Aug 2020  路  5Comments  路  Source: PowerShell/PowerShell

Not really a bug but:

https://github.com/PowerShell/PowerShell/blob/904e5511789f0a8375c23c9a1ee59918be0a82a1/src/System.Management.Automation/engine/parser/Compiler.cs#L952-L955

And the method in the select:

https://github.com/PowerShell/PowerShell/blob/904e5511789f0a8375c23c9a1ee59918be0a82a1/src/System.Management.Automation/engine/parser/Compiler.cs#L941-L950

That method is used to compile method arguments, the result is then enumerated twice (once in the first highlighted line, one is the last):

https://github.com/PowerShell/PowerShell/blob/904e5511789f0a8375c23c9a1ee59918be0a82a1/src/System.Management.Automation/engine/parser/Compiler.cs#L6338-L6344

This causes all method arguments to be compiled twice due to multiple enumeration. I'm not aware of any bugs due to this behavior, but it probably negatively impacts compile time for complicated member invocations. Also the method supplied to Select is not done in such a way that the delegate can be cached per instance by roslyn.

Issue-Question Resolution-Fixed WG-Engine WG-Engine-Performance

Most helpful comment

Thanks @SeeminglyScience! I submitted the PR #13491 to fix this, please take a look if you have time.

All 5 comments

/cc @daxian-dbw

@SeeminglyScience Could you please create a simple repro so that we can measure performance impact since you mentioned this?

@SeeminglyScience Could you please create a simple repro so that we can measure performance impact since you mentioned this?

In theory something like this should be significantly faster after a fix:

Appx.format.ps1xml as XElement (Click to expand)

using namespace System.Xml.Linq

$document = [XElement]::new('Configuration',
  [XElement]::new('ViewDefinitions',
      [XElement]::new('View',
          [XElement]::new('Name', 'TableView'),
          [XElement]::new('ViewSelectedBy',
              [XElement]::new('TypeName', 'AppxDeploymentEventLog')),
          [XElement]::new('TableControl',
              [XElement]::new('TableHeaders',
                  [XElement]::new('TableColumnHeader',
                      [XElement]::new('Label', 'Time'),
                      [XElement]::new('Width', 25)),
                  [XElement]::new('TableColumnHeader',
                      [XElement]::new('Label', 'ID'),
                      [XElement]::new('Width', 12)),
                  [XElement]::new('TableColumnHeader',
                      [XElement]::new('Label', 'Message'))),
              [XElement]::new('TableRowEntries',
                  [XElement]::new('TableRowEntry',
                      [XElement]::new('TableColumnItems',
                          [XElement]::new('TableColumnItem',
                              [XElement]::new('ScriptBlock', '$_.timecreated')),
                          [XElement]::new('TableColumnItem',
                              [XElement]::new('ScriptBlock', '$_.id')),
                          [XElement]::new('TableColumnItem',
                              [XElement]::new('ScriptBlock', '$_.message')),
                      [XElement]::new('Wrap', @())))))),
      [XElement]::new('View',
          [XElement]::new('Name', 'TableView'),
          [XElement]::new('ViewSelectedBy',
              [XElement]::new('TypeName', 'Microsoft.Windows.Appx.PackageManager.Commands.AppxPackage')),
          [XElement]::new('ListControl',
              [XElement]::new('ListEntries',
                  [XElement]::new('ListEntry',
                      [XElement]::new('ListItems',
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'Name')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'Publisher')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'Architecture')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'ResourceId')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'Version')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'PackageFullName')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'InstallLocation')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'IsFramework')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'PackageFamilyName')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'PublisherId')),
                          [XElement]::new('ListItem',
                              [XElement]::new('PropertyName', 'PackageUserInformation'),
                              [XElement]::new('ItemSelectionCondition',
                                  [XElement]::new('ScriptBlock', '($_.PackageUserInformation.Count -gt 0)'))),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'IsResourcePackage')),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'IsBundle')),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'IsDevelopmentMode')),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'NonRemovable')),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'Dependencies'),
                            [XElement]::new('ItemSelectionCondition',
                              [XElement]::new('ScriptBlock', '($_.Dependencies.Count -gt 0)'))),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'IsPartiallyStaged')),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'SignatureKind')),
                          [XElement]::new('ListItem',
                            [XElement]::new('PropertyName', 'Status')))))))))

If I'm reading it right the inner most nodes will be compiled quite a few times.

Thanks @SeeminglyScience! I submitted the PR #13491 to fix this, please take a look if you have time.

:tada:This issue was addressed in #13491, which has now been successfully released as v7.1.0-preview.7.:tada:

Handy links:

Was this page helpful?
0 / 5 - 0 ratings