This directory contains useful scripts and related files for analyzing PowerShell performance.
If you use the Windows Performance Toolkit, you can use the following to collect data and analyze a trace.
$PowerShellGitRepo = "D:\PowerShell"
wpr -start $PowerShellGitRepo\tools\performance\PowerShell.wprp -filemode
pwsh.exe -NoProfile -Command "echo 1"
wpr -stop PowerShellTrace.etl
wpa -i wpa://.\PowerShellTrace.etl?profile=$PowerShellGitRepo\tools\performance\PowerShell.wpaProfileWhen wpa opens, under System Activity, you'll find a section "Regions of Interest". With the above wpaProfile, you should see a bunch of PowerShell related regions as well as GC and JIT activity.
If you use PerfView, you can collect a trace by running
Invoke-PerfviewPS.ps1 -scenario { echo 1 }
perfview .\perfviewdata.etlThe etl files collected with perfview or wpr should contain roughly the same events.
Also note that you can collect the trace with one tool and analyze with the other.
SelectString.wpaProfile derives from the general profile, puts sampled CPU
stacks first, and uses SelectString.stacktags instead of script-focused tags
and regions. It retains the shared GC/JIT regions. Process, thread, CPU, module,
function and stack-tag columns help separate engine work from runtime and pipeline
costs. Open a captured trace with:
$profile = Join-Path $PowerShellGitRepo 'tools/performance/SelectString.wpaProfile'
wpa.exe -i C:\Traces\candidate-DenseContext.etl -profile $profileUse the focused capture in test/perf/SelectString/New-EtwCapture.ps1. Filter to
the benchmark worker PID (recorded in the JSON) and select the measured-iteration
regions from SelectString.Regions.xml. Warmup and optional counting have separate
regions; capture runs skip counting by default. Marker boundaries surround the
measurement bookkeeping as well as the timed call. Compare CPU
sample weights, GC pauses and JIT activity separately; inclusive stack categories
are not additive exclusive costs. Tags cover shipping and extracted engine names,
but inlining or unresolved symbols can hide frames. Verify tag matches against
the raw stacks before using them for attribution. JIT regions accept completion
event versions 1 and 2; validate pairing in a real trace. Region duration across
threads is not total JIT CPU time.
The focused capture does not collect context switches or disk I/O. Sampled CPU does not measure blocked time; use the general capture profile if those become the next question. The analysis profile and tags need validation in WPA against the collected trace; XML validation alone does not establish correct attribution.
PDB files are not published for PowerShell Core,
so the current recommendation is to build PowerShell yourself passing -CrossGen to Start-Build.
If profiling Windows PowerShell, symbols are generated from GAC. wprui.exe and perfview.exe will both generate the PDB files needed.
| File | Description |
|---|---|
| GC.Regions.xml | WPA regions of interest for GC |
| JIT.Regions.xml | WPA regions of interest for JIT |
| PowerShell.Regions.xml | WPA regions of interest for PowerShell |
| PowerShell.stacktags | PowerShell stack tags |
| PowerShell.wpaProfile | WPA profile to load regions of interest and stack tags |
| PowerShell.wprp | WPR profile to enable CLR and PowerShell ETW events |
| Invoke-PerfviewPS.ps1 | Script to run perfview and with PowerShell ETW events enabled |