Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get-ChildItem to a file is 2x slower than CMD #12817

Closed
asklar opened this issue May 27, 2020 · 10 comments
Closed

Get-ChildItem to a file is 2x slower than CMD #12817

asklar opened this issue May 27, 2020 · 10 comments
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-Duplicate The issue is a duplicate.

Comments

@asklar
Copy link

asklar commented May 27, 2020

Steps to reproduce

(Measure-Command { dir -Recurse C:\rnw | Out-File C:\temp\1.txt }).TotalSeconds

takes 15.222019 seconds
whereas CMD:

C:\temp\timecmd.cmd "dir /s C:\rnw > C:\temp\1.txt"

command took 0:0:8.47 (8.47s total)

Expected behavior

Same performance as CMD.

Actual behavior

2x slower than CMD

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.1
PSEdition                      Core
GitCommitId                    7.0.1
OS                             Microsoft Windows 10.0.20133
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
@asklar asklar added the Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a label May 27, 2020
@p0W3RH311
Copy link

p0W3RH311 commented May 27, 2020

1- in your ps code you use pipeline and pipeline inn PS is not like pipeline in UNIX. with PS pipeline is very powerful but slow
2- every cmdlet is aa object in your case every object passed throw pipeline is passed is an object (structured object) and not string as cmd
3- in cmd eveery commaand have here owwn parser in PS is one parser for every command aand one formater for all cmdlet

@iSazonov iSazonov added the Resolution-Duplicate The issue is a duplicate. label May 27, 2020
@iSazonov
Copy link
Collaborator

It is tracked in #3575

@asklar
Copy link
Author

asklar commented May 27, 2020

@p0W3RH311 @iSazonov using redirection instead of pipe, is even worse:

PS C:\rnw> (Measure-Command { dir -Recurse C:\rnw > C:\temp\1.txt }).TotalSeconds
18.5898439

The fact that everything is an object doesn't matter, that's an implementation detail. If we are pushing people away from CMD and onto PS as a replacement, then its performance must be comparable, and any overhead must be pay-for-play, and not affect the general case where I don't use any of the objects explicitly.

@vexx32
Copy link
Collaborator

vexx32 commented May 27, 2020

Yeah, redirection to a file in PS is identical to | Out-File -Path $path so it incurs the same overhead. If you want to avoid some of the overhead of the formatter, you can just pull off the text properties that you actually need, or use a cmdlet designed to work with text rather than wasting time formatting everything (like Out-File does):

# Set-Content coerces the input to string instead of sending it through the formatter
Measure-Command {
     Get-ChildItem -Recurse C:\rnw | Set-Content -Path C:\temp\1.txt
}

# Pull off the property you want to store; Out-File vs Set-Content here will be about the same
Measure-Command {
    Get-ChildItem -Recurse C:\rnw |
        Select-Object -Property FullName |
        Out-File -Path C:\temp\1.txt
}

The formatter exists for convenience and making the shell experience more user-friendly. If you don't want the overhead it brings, there are plenty of avenues available to you to speed things up. 🙂

@powercode
Copy link
Collaborator

powercode commented May 28, 2020

function cmddir($dir){cmd /c dir /S $dir}

Same speed, same functionality.
We will pay an overhead for using .net objects. That is not just an implementation detail.
That said, there are many things that can be improved performance-wise.
Runtime-performance was not a primary concern during the initial development of PowerShell, and sometimes it shows.

@iSazonov
Copy link
Collaborator

@asklar What is a result for:
(Measure-Command { dir -Name -Recurse C:\rnw > C:\temp\1.txt }).TotalSeconds

@lukeb1961
Copy link

PWSH> $PSversiontable

Name Value


PSVersion 7.1.0-preview.2
PSEdition Core
GitCommitId 7.1.0-preview.2
OS Microsoft Windows 10.0.19631
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0

PWSH> (Measure-Command { CMD /c DIR /S 'C:\Program Files\PowerShell' > C:\temp\1.txt }).TotalSeconds
0.2031207
PWSH> (Measure-Command { GCI -Name -Recurse 'C:\Program Files\PowerShell' > C:\temp\2.txt }).TotalSeconds
0.8576304
PWSH> (Measure-Command { GCI -Recurse 'C:\Program Files\PowerShell' | Select-Object -Property FullName | Out-File -Path C:\temp\3.txt }).TotalSeconds
0.2609885

@iSazonov
Copy link
Collaborator

For cmd.exe more correct test is:

cmd /v:on /c "echo !TIME! &  DIR /S "C:\Program Files\PowerShell" > C:\tmp\1.txt & echo !TIME!"

@iSazonov
Copy link
Collaborator

For Get-ChildItem -Recurce -Name you can test with artifact from #12834.

@ghost
Copy link

ghost commented May 30, 2020

This issue has been marked as duplicate and has not had any activity for 1 day. It has been closed for housekeeping purposes.

@ghost ghost closed this as completed May 30, 2020
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-Duplicate The issue is a duplicate.
Projects
None yet
Development

No branches or pull requests

6 participants