Настройка науки
Сначала несколько скриптов, которые помогут нам проверить это. Это создает 2000 файлов сценариев, каждый из которых имеет одну маленькую функцию:
1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }
Этого должно быть достаточно, чтобы обычные издержки запуска не имели большого значения. Вы можете добавить больше, если хотите. Это загружает их все, используя точечный источник:
dir test*.ps1 | % {. $_.FullName}
Это загружает их всех, сначала читая их содержимое:
dir test*.ps1 | % {iex (gc $_.FullName -Raw)}
Теперь нам нужно провести серьезную проверку работы PowerShell. Мне нравится JetBrains dotPeek для декомпилятора. Если вы когда-либо пытались встроить PowerShell в приложение .NET, вы обнаружите, что сборка, которая включает в себя большинство соответствующих компонентов, - это System.Management.Automation
Декомпилируйте это в проект и PDB.
Чтобы увидеть, где проводится все это таинственное время, мы будем использовать профилировщик. Мне нравится тот, который встроен в Visual Studio. Это очень просто в использовании. Добавьте папку, содержащую PDB, в расположение символов. Теперь мы можем выполнить профилирование экземпляра PowerShell, который просто запускает один из тестовых сценариев. (Установите параметры командной строки, чтобы использовать -File
с полным путем первого сценария, чтобы попробовать. Установите место запуска для папки, содержащей все крошечные сценарии.) После этого откройте запись "Свойства" в powershell.exe
разделе "Цели" и измените аргументы для использования другого сценария. Затем щелкните правой кнопкой мыши самый верхний элемент в Performance Explorer и выберите Start Profiling. Профилировщик снова запускается с использованием другого сценария. Теперь мы можем сравнить. Убедитесь, что вы нажимаете "Показать весь код", если вам предоставлена опция для меня это отображается в области уведомлений в сводном представлении примера отчета о профилировании.
Результаты приходят в
На моем компьютере версия Get-Content
заняла 9 секунд, чтобы просмотреть файлы сценариев 2000 года. Важными функциями "Горячего пути" были:
Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord
Это имеет большой смысл: нам нужно подождать, пока Get-Content
прочитает контент с диска, и нам нужно подождать, пока Invoke-Expression
использует это содержимое.
В версии с точечным источником моя машина потратила чуть более 15 секунд на обработку этих файлов. На этот раз функции на Hot Path были нативными методами:
WinVerifyTrust
CodeAuthzFullyQualifyFilename
Второй из них, по-видимому, недокументирован, но WinVerifyTrust
«выполняет действие проверки доверия для указанного объекта». Это настолько неопределенно, насколько это возможно, но, другими словами, эта функция проверяет подлинность данного ресурса с помощью данного поставщика. Обратите внимание, что я не включил какие-либо необычные средства безопасности для PowerShell, и моя политика выполнения сценариев не Unrestricted
.
Что это значит
Короче говоря, вы ожидаете, что каждый файл будет каким-то образом проверен, возможно, проверен на подпись, хотя это не является необходимым, если вы не ограничиваете скрипты, которые разрешено запускать. Когда вы gc
, а затем iex
содержания, это как вы ввели функции на консоли, так что нет ресурсов для проверки.