PowerShell / PSReadLine

A bash inspired readline implementation for PowerShell
BSD 2-Clause "Simplified" License
3.73k stars 295 forks source link

Set-PSReadLineOption is slow when called from profile #4022

Open RoadToDream opened 5 months ago

RoadToDream commented 5 months ago

Prerequisites

Exception report

N/A

Screenshot

measure-command { Set-PSReadLineOption -HistoryNoDuplicates -EditMode Windows }

image image

Environment data

PS Version: 7.4.2
PS HostName: ConsoleHost
PSReadLine Version: 2.3.5
PSReadLine EditMode: Windows
OS: 10.0.22621.1 (WinBuild.160101.0800)
BufferWidth: 181
BufferHeight: 23

Steps to reproduce

This has been reported in #476, but closed without much context been provided. Set-PSReadLineOption calling from profile will take much longer than calling from a running pwsh. Adding a single line of Set-PSReadLineOption in profile delays start up time over 100 ms. I wonder how is the 11 ms load time is achieved mentioned in that issue and what can I do to ease the issue.

Expected behavior

Same execution time when running from profile.

Actual behavior

Much longer execution time in profile.

daxian-dbw commented 4 months ago

Do you mean Set-PSReadlineOption is slow in general or only the Set-PSReadLineOption -HistoryNoDuplicates -EditMode Windows is slow for you?

Adding a single line of Set-PSReadLineOption in profile delays start up time over 100 ms.

I cannot reproduce the issue locally. I have 3 calls to Set-PSReadlineOption in my profile and cannot observe a delay as reported

RoadToDream commented 4 months ago

Hi, for me it's the general Set-PSReadlineOption. Even a single Set-PSReadlineOption will introduce over 100 ms delay. If it's not reproducible I assume there is something wrong from my end, may I ask if there is any log I may collect that can help diagnose this issue? Thanks

daxian-dbw commented 4 months ago

Even Set-PSReadlineOption -BellStyle None takes over 100ms for you in profile?

may I ask if there is any log I may collect that can help diagnose this issue?

If you really want to dig into it, I guess you will have to collect traces using prefview, which is not easy for a starter.

You will need to build PSReadLine locally with the Release configuration .\build.ps1 -Framework net462 -Configuration Release and use the produced module to collect the trace. After the build, you can find the produced PSReadLine module under .\bin\Release\PSReadLine, and the .pdb file for Microsoft.PowerShell.PSReadLine2.dll can be found under .\PSReadLine\bin\Release\net462.

RoadToDream commented 4 months ago

That's true. image

Thanks for the instruction. I am indeed a starter for C# but will give it a try

daxian-dbw commented 4 months ago

There are other ways for profiling, maybe easier than using the perfview. See https://github.com/dotnet/performance/blob/main/docs/profiling-workflow-dotnet-runtime.md https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-trace

gwojan commented 4 months ago

Hi, for me it's the general Set-PSReadlineOption. Even a single Set-PSReadlineOption will introduce over 100 ms delay. If it's not reproducible I assume there is something wrong from my end, may I ask if there is any log I may collect that can help diagnose this issue? Thanks

Just out of curiosity do you have some other software running that might be causing issues, ie: Defender, FireEye, etc. My work laptop frequently has performance issues running my wacky PowerShell profile because of those two specific applications scanning all the things. 😭

My latest issue was I have a function Get-Fortune which calls into WSL using fortune, cowsay, and lolcat to display my fortune in each new PowerShell session. About two weeks ago my profile load times went from maybe one second to 35 seconds! It turns out I have a really old script that maps a persistent drive to a now non-existent resource. Waiting for WSL was causing my extreme slowdowns so once I removed the mapped drive performance was back to normal.

RoadToDream commented 4 months ago

Thanks for the suggestion. I can take a look, but honestly, I don't think that's the reason. I have disabled Defender.

RoadToDream commented 4 months ago

Let me put some profiling result here. I am using prefview to profile, each configuration is executed 10 times for averaging.

image Fig. 1 With PSReadLine option: Set-PSReadLineOption -EditMode Emacs

image Fig. 2 Without PSReadLine option

RoadToDream commented 4 months ago

Flame graphs image Fig. 1 With PSReadLine option: Set-PSReadLineOption -EditMode Emacs image Fig. 2 Without PSReadLine option

RoadToDream commented 4 months ago

PerfViewDataNoOptionLoop.View1.perfView.xml.zip PerfViewDataWithOptionLoop.View1.perfView.xml.zip

RoadToDream commented 4 months ago

I am not sure if this information is sufficient to help diagnose the issue, but if not, please let me know and I can provide more details. I am much more familiar with VTune, so if that would help, I can provide information from that as well.

Based on my findings so far, the issue seems more likely to be related to PowerShell rather than PSReadLine.

StevenBucher98 commented 4 months ago

Just out of curiosity does the startup time only increase with that particular command or does it increase with anything in your profile?

RoadToDream commented 4 months ago

Hi @StevenBucher98, it increases with any line with Set-PSReadlineOption. However, adding one config line of Set-PSReadlineOption takes about same time as adding four or five.

konosubakonoakua commented 2 months ago

Same here.