Powershell: pwsh загружается в 2 раза медленнее, чем powershell

Созданный на 21 мар. 2018  ·  39Комментарии  ·  Источник: PowerShell/PowerShell

Powershell 6 запускается медленно по сравнению с powershell

function time($block) {
    $sw = [Diagnostics.Stopwatch]::StartNew()
    &$block
    $sw.Stop()
    $sw.Elapsed
}

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      17115  1

vs

Major  Minor  Patch  PreReleas BuildLabel
                     eLabel
-----  -----  -----  --------- ----------
6      0      2


mus@mus-laptop ~
> time {powershell -NoProfile -c exit}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 233
Ticks             : 2337327
TotalDays         : 2.70523958333333E-06
TotalHours        : 6.492575E-05
TotalMinutes      : 0.003895545
TotalSeconds      : 0.2337327
TotalMilliseconds : 233.7327



mus@mus-laptop ~
> time {pwsh -NoProfile -c exit}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 540
Ticks             : 5400421
TotalDays         : 6.25048726851852E-06
TotalHours        : 0.000150011694444444
TotalMinutes      : 0.00900070166666667
TotalSeconds      : 0.5400421
TotalMilliseconds : 540.0421





> time {cmd /c exit}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : **42**
Ticks             : 426119
TotalDays         : 4.93193287037037E-07
TotalHours        : 1.18366388888889E-05
TotalMinutes      : 0.000710198333333333
TotalSeconds      : 0.0426119
TotalMilliseconds : 42.6119



Winver: 17115.1

WG-Engine-Performance

Самый полезный комментарий

Я чувствую, что этот разговор стал излишне оборонительным.

Все мы знаем, что некоторые из упомянутых инструментов похожи на сравнение седана с купе. И что? Хотите начать сравнивать производительность реальных скриптов в этих инструментах, выполняющих актуальные задачи? _Ничего из этого на самом деле не имеет значения, потому что простая тема в исходном сообщении верна: _

Время запуска PowerShell 6.0.2 примерно вдвое больше , чем у PowerShell 5.1.

Время запуска других языков сценариев просто служит для оценки скорости: даже если она измеряется в миллисекундах, даже «более высокая» скорость оказывается медленной.

Все 39 Комментарий

Похоже, сборки не перекрестно генерируются, поэтому JIT влияет на время запуска.

PS C:\Program Files\PowerShell\6.0.1> [System.Reflection.AssemblyName]::GetAssemblyName("${pwd}\System.Management.Automation.dll") | fl *


Name                  : System.Management.Automation
Version               : 6.0.1.0
CultureInfo           :
CultureName           :
CodeBase              :
EscapedCodeBase       :
ProcessorArchitecture : MSIL
ContentType           : Default
Flags                 : PublicKey
HashAlgorithm         : SHA1
VersionCompatibility  : SameMachine
KeyPair               :
FullName              : System.Management.Automation, Version=6.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

Похоже сборки перекрещиваются. Однако получение множества сообщений от crossgen.exe о том, что некоторые вещи не поддерживаются, что означает, что эти методы остаются как MSIL (что, вероятно, объясняет, почему сборка говорит, что это MSIL). Это также означает, что MSIL должен быть JIT при запуске. Я думаю, это то, что влияет на производительность стартапа. Нам нужно будет продолжить расследование, чтобы узнать, можем ли мы что-нибудь здесь сделать.

Честно говоря, даже PowerShell 5 очень медленный (в 6 раз медленнее), чем CMD. Было бы хорошо, если бы powershell 6 был в 2-3 раза быстрее, чем cmd.

Например, на моем компьютере python запускается всего в 2 раза медленнее, чем CMD ...

Было бы здорово иметь лучшее время запуска, поскольку к этому добавляются настраиваемые профили. Но, честно говоря, PowerShell легко компенсирует эти секунды, когда дело доходит до выполнения работы (не только с точки зрения времени выполнения, но и времени для написания кода / команды) 😄

Было бы здорово иметь лучшее время запуска, поскольку к этому добавляются настраиваемые профили. Но, честно говоря, PowerShell легко компенсирует эти секунды, когда дело доходит до выполнения работы (не только с точки зрения времени выполнения, но и времени для написания кода / команды) 😄

Честно говоря, это не очень хороший аргумент. То же самое можно сказать о времени запуска Windows или времени запуска Python. Первая загрузка / запуск очень важна.

С другой стороны, cmd.exe - это собственный исполняемый файл, который практически ничего не делает при запуске. pwsh.exe - это управляемый исполняемый файл, который устанавливает сложную среду выполнения.

Мы, конечно, должны стремиться улучшить производительность запуска, но сравнение с совершенно разными средами с очень разными возможностями не совсем актуально.

С другой стороны, cmd.exe - это собственный исполняемый файл, который практически ничего не делает при запуске. pwsh.exe - это управляемый исполняемый файл, который устанавливает сложную среду выполнения.

Мы, конечно, должны стремиться улучшить производительность запуска, но сравнение с совершенно разными средами с очень разными возможностями не совсем актуально.

Согласен, поэтому я включил производительность Powershell 6 и Python 3 относительно CMD. Кажется, что PowerShell должен быть в 2-3 раза быстрее, чем CMD, что приводит его в соответствие с другими интерактивными языками.

Согласен, поэтому я включил производительность Powershell 6 и Python 3 относительно CMD. Кажется, что PowerShell должен быть в 2-3 раза быстрее, чем CMD, что приводит его в соответствие с другими интерактивными языками.

«Интерактивность» - лишь одна из многих черт. Окружающая среда очень разная.
PowerShell имеет адаптируемую систему типов, которая абстрагирует множество различных базовых систем типов. Он имеет расширяемую систему форматирования, которая преобразует объекты в текст. Он имеет конвейер на основе объектов. Он имеет настраиваемую подсказку, завершение табуляции и т. Д.

Все это требует времени для инициализации, особенно расширяемых типов и систем форматирования.

Как сказал Стив, существует проблема, связанная с тем, что сборки не перекрестно генерируются должным образом, поэтому мы тратим довольно много дополнительного времени на работу с IL. Это должно быть исправлено.

Но даже с этим исправлением существуют различия в области действия и зависимостях от CLR / DLR, из-за которых запуск Powershell будет медленнее, чем cmd и python.

Рискну предположить, что если бы у Python был более выразительный REPL и глубокая структура, доступная и готовая к использованию в первой строке, время его загрузки было бы на уровне pwsh . Я видел множество скриптов Python с длительным временем инициализации из-за загрузки зависимостей для более продвинутого использования. По умолчанию Python запускается быстро, потому что по умолчанию он загружается с меньшим количеством доступных. Сравнивать время запуска между PowerShell и другими оболочками и языками сценариев немного сложно, если они все не близки по паритету функций по умолчанию. Ни один из языков, с которыми я работал, по умолчанию не имеет такой кашицы, как PowerShell (к лучшему или к худшему).

Одна из идей состоит в том, чтобы выполнить джиттинг при первом вызове функции (что сделает первый вызов функции медленным, а последующие вызовы - быстрыми). В дополнение к этому, набор часто используемых функций может быть предварительно скомпилирован / модифицирован при запуске.

@musm , весь продукт перекрестный: изд. В начале @ SteveL-MSFT сказал, что что-то в этом процессе дает сбой, что замедляет запуск процесса.

Я не думаю, что мы можем многое сделать в 6.1.0. Мы продолжим работу с командой dotnetcore.

Я чувствую, что этот разговор стал излишне оборонительным.

Все мы знаем, что некоторые из упомянутых инструментов похожи на сравнение седана с купе. И что? Хотите начать сравнивать производительность реальных скриптов в этих инструментах, выполняющих актуальные задачи? _Ничего из этого на самом деле не имеет значения, потому что простая тема в исходном сообщении верна: _

Время запуска PowerShell 6.0.2 примерно вдвое больше , чем у PowerShell 5.1.

Время запуска других языков сценариев просто служит для оценки скорости: даже если она измеряется в миллисекундах, даже «более высокая» скорость оказывается медленной.

Я бы тоже закрылся, потому что регресс, который когда-то случился, исправлен, и теперь 6.1 запускается как ракета.

Я не вижу каких-либо улучшений во времени запуска в версии 6.1 preview-3. К сожалению, 6.1 запускается медленнее, чем 5.1 и 6.0.2, учитывая все разговоры об улучшении производительности в .NET Core 2.1:
image

Powershell 5.1 против Powershell 6.2:

2019-06-18-11-05-45

Имя ОС: Microsoft Windows Server 2016 Standard.
Версия ОС: 10.0.14393 Н / Д, сборка 14393

Похоже, у нас все еще есть проблема с 7-preview.1. Команда .NET уже работает над улучшением запуска, мы должны продолжать проверять это с помощью новых превью.

PS C:\Users\slee> $total = 0; 1..100 | % { $total += (Measure-Command { powershell -nop -nologo -c 1 }).TotalMilliseconds };$total/100
190.219938
PS C:\Users\slee> $total = 0; 1..100 | % { $total += (Measure-Command { pwsh-preview -nop -nologo -c 1 }).TotalMilliseconds };$total/100
452.461919
PS C:\Users\slee> $total = 0; 1..100 | % { $total += (Measure-Command { pwsh -nop -nologo -c 1 }).TotalMilliseconds };$total/100
346.560211
> $total = 0; 1..100 | % { $total += (Measure-Command { pwsh-preview -nop -nologo -c 1 }).TotalMilliseconds };$total/100;
394.33809

все еще довольно медленно на 7.0.0-preview.2 , а также

Для однострочных слов Стива у меня есть (в Windows):

| Версия для PS | Время (мс) |
| ----------- | ----------- |
| 5.1 | 404 |
| 6.2.2 | 444 |
| 7.0.0-preview.2 | 546 |
| 7.0.0-dailypreview3-30639 | 494 |

Очевидно, мы добавили некоторые коммиты во время 7.0 Preview3, которые замедляют запуск по сравнению с 6.2.
Я подготовил исправление, которое убирает ~ 10 мс в тесте Стива.
И я думаю об еще одном исправлении, которое, надеюсь, сэкономит несколько мс.

Я часто решал использовать bash (через git для Windows, а не WSL) просто потому, что он запускается «почти мгновенно». Powershell (любая версия, которую я пробовал, включая Core / 6) достаточно медленная на машине, которую я должен использовать на работе.

Медленный запуск также является серьезной критикой, которую я слышал от многих Linux-людей, с которыми я разговаривал. Я убедил некоторых из них, что структурированные объекты лучше текста, но время запуска и общая медлительность по сравнению с другими оболочками их отталкивают.

Еще предстоит проделать работу по улучшению производительности при запуске. Используя обновленную версию моего теста :

PSVersion       Time (ms)
---------       ---------
5.1.18362.10000    169.64
6.2.1              311.96
7.0.0-preview.3    399.98

Обратите внимание, что без серьезных изменений вряд ли мы будем так же быстро, как 5.1, потому что он использует ngen, что означает, что .NET Framework выполняет собственную компиляцию для вашей конкретной системы при первом холодном запуске powershell.exe. .NET Core не имеет ngen, поэтому мы полагаемся на crossgen для предварительной компиляции в целевую архитектуру, но crossgen не так полон, как ngen при создании собственного кода, потому что он предварительно скомпилирован, а не во время выполнения.

Хотя дальнейшая оптимизация запуска была бы приятной, мы не должны забывать, что производительность при запуске - это одно, но общая производительность PowerShell также играет важную роль, поскольку потенциально можно сэкономить больше времени. Мой профиль занимает почти секунду из-за того, что некоторые модули, такие как posh-git , загружаются долго. Благодаря общим улучшениям, 7.0 все еще быстрее, чем 6.2, и я могу использовать его просто потому, что мой $Profile загружается быстрее. Из любопытства: можно ли, например, импортировать модуль неблокирующим способом, поскольку в этом сценарии задания не работают? Использование Invoke-Pester в первый раз занимает второе место, а также в первый раз из-за того, что модуль необходимо импортировать (модуль в настоящее время не оптимизирован с помощью шаблона построителя модулей, чтобы сжать все в монолитный файл во время сборки) и я вижу эту часть негативного, запаздывающего опыта, который PowerShell имеет в некоторых сценариях (даже не заставляйте меня начинать завершение вкладки, которое иногда занимает секунды, и даже отмена этого занимает много времени ...)

После того, как мы широко использовали PowerShell 2/3 в Windows, а затем широко использовали bash / sh в Linux, разница во времени запуска просто ошеломляет.

Когда кому-то в Linux действительно больно, так это при запуске исполняемых скриптов с использованием shebang. Обычно с bash вы пишете много скриптов с помощью shebang, например, #!/usr/bin/env bash

вы также можете запускать несколько сценариев подряд, которые вызывают другие сценарии, которые также используют shebang

например

./foo

#!/usr/bin/env bash

./bar

./бар

#!/usr/bin/env bash

echo "Hello from bar!"

С bash / sh это не проблема, вы действительно не замечаете никаких проблем со скоростью при открытии подоболочек / новых процессов, подобных этому.

Вы также можете вызывать множество исполняемых скриптов подряд из интерактивной оболочки.

Причина, по которой это имеет значение, заключается в том, что с pwsh использование shebang ( #!/usr/bin/env pwsh ) приводит к тому, что каждый сценарий выполняется так же медленно, как и этот «первый запуск».

Это означает, что в приведенном выше примере вызов foo займет в 2 раза больше времени, чем просто запуск pwsh .

Это также означает, что выполнение нескольких сценариев PowerShell (использующих shebangs) в интерактивной оболочке (например, из bash или даже из PowerShell) происходит очень медленно.

Сравните это с тем, когда вы сначала запускаете pwsh , а затем изнутри этой оболочки запускаете те же сценарии, но как файлы .ps1 а не полагайтесь на shebang. Он выполняется практически мгновенно (в рамках существующего процесса pwsh).

Для меня это самая большая проблема с медленным запуском pwsh. Дело не в том, что в первый раз запускается медленно, а в том, что использование shebangs означает, что каждый вызов будет медленнее или медленнее.

Переход от использования shebang к тому, чтобы все набирали pwsh -File foo.ps1 или что-то еще, не является плавным переходом. Исходя из опыта, я никогда не вызываю сценарии bash, набирая bash foo.bash , я делаю их исполняемыми и вызываю их напрямую.

Мой профиль занимает почти секунду из-за того, что некоторые модули, такие как posh-git, загружаются долго.

даже не заставляйте меня начинать с завершения табуляции, которое иногда занимает секунды, а даже отмена занимает много времени ....

Похоже, что корень проблемы обсуждается в # 10309 - Более безопасный API заметно замедляет путь кода модуля импорта (есть дополнительный двойной вызов более безопасного API!).

Я все еще обнаруживаю, что pwsh в последней версии в два раза медленнее, чем в PowerShell.

Процитировал мой комментарий по связанной проблеме https://github.com/PowerShell/PowerShell/issues/7402#issuecomment -576943388

С 5.1 по 6.0 / 6.1 / 6.2 худшее время запуска было в основном из-за использования crossgen сравнению с ngen . ngen , который используется powershell.exe , генерирует более эффективный код, поскольку он нацелен на конкретную машину, на которой выполняется код; в то время как crossgen должен нацеливаться на широкий спектр машин и, таким образом, генерирует менее эффективный, но более устойчивый код.
Во временном интервале 6.2 # 8341 улучшило время запуска примерно на 25% по сравнению с 6.1.

С 6.2 до 7.0 время запуска сократилось в основном из-за того, что .NET Core начал использовать формат Ready-to-Run для System.Private.CoreLib.dll и, возможно, нескольких других основных библиотек. Они были созданы ранее.

Можно ли это скомпилировать с помощью CoreRT?

Цитата из CoreRT README.md:

Неподдерживаемые функции: динамическая загрузка (например, Assembly.LoadFile), динамическое создание кода (например, System.Reflection.Emit), специфичное для Windows взаимодействие (например, COM, WinRT)

PowerShell зависит от среды выполнения динамического языка (DLR), которая сильно зависит от генерации динамического кода. Кроме того, динамическая загрузка является фундаментальным требованием для PowerShell.

Powershell 7 раз:

image

pwsh в 2,2 раза медленнее, чем powershell

Я собирался обновиться, потому что 5.1 имеет проблему со шрифтом, но версия 7 вдвое меньше скорости, как говорили другие.

@ nu8 Для ясности, это только стартап, страдающий от снижения производительности. Стабильная производительность во время выполнения намного лучше в PowerShell 7. Поэтому, если вы не сильно полагаетесь на pwsh -c или pwsh -file в своем ежедневном рабочем процессе, вам должно быть хорошо перейти на PowerShell 7.

Это как раз проблема и причина, по которой я открыл этот @ nu8.

Я подозреваю, что мы не единственные, кто проповедует об этом.

Я щелкаю правой кнопкой мыши и открываю PowerShell в текущем каталоге много раз в день. Это мучительно медленно, особенно если сравнивать с почти мгновенным временем, скажем, запуска WSL.

Тестирование здесь проводится без загрузки профиля ( -NoProfile ) и без учета времени запуска оболочки почти в 1 секунду. Я бы посчитал даже 0,1 секунды немного медленным.

| Версия | Время запуска |
| - | - |
| 5 | 0,3 с |
| 6.2.3 | 4.5 с |
| 7.0.2 | 0,6 с |

Имейте в виду, что с включенными плагинами запуск пострадает еще больше. У меня включены два плагина: PoshGit и Z-AutoJump. Время моего запуска с этими двумя плагинами:

| Версия | Время запуска |
| - | - |
| 5 | 2,0 с |
| 6.2.3 | 4.8 с |
| 7.0.2 | 2.2с |

Сравните это со временем запуска в macOS (iTerm):
| Оболочка | Время запуска |
| - | - |
| zsh 5.7.1 (без плагинов) | 0.00s |
| zsh 5.7.1 (с большим количеством плагинов) | 0.14s |
| pwsh 7.0.0 (без плагинов) | 0.43s |

@Bouke полностью согласен. Обратите внимание, что posh-git, как известно, плохо подходит для добавления как минимум 500 мс ко времени начала.

И да, даже 1 секунда - смешное время старта для интерактивной оболочки. Для лучшего UX время начала должно быть меньше 100 мс.

Как для кого-то, у кого pwsh в качестве оболочки по умолчанию в Linux, это сильно влияет на меня, поэтому я был бы очень признателен за любое возможное улучшение! Мало того, что окно терминала запускается заметно медленнее, я просто не могу запускать быстрые сценарии PowerShell на моих горячих клавишах. (На что у меня есть немало таких вещей, на которые я полагаюсь, так как я использую Sway в качестве оконного ящика.)

Мне нужно вернуться к bash или perl для этих целей, которые намного раздражают писать что-то в, чем powershell, который, на мой взгляд, намного лучше в целом, поэтому я придерживаюсь его, хотя есть немало мелких неудобств. (Например, отсутствует оператор перенаправления файла '<', что ожидается некоторыми программами, такими как vim, но, к счастью, это можно исправить, указав вместо этого использовать каналы.)

В любом случае, некоторые обновления, которые делают pwsh -c жизнеспособными для более или менее мгновенных мелочей, были бы очень кстати!
Спасибо за всю работу команды разработчиков, моя жизнь уже стала намного лучше, если у меня есть оболочка с правильным синтаксисом и возможностью программирования (например, | % { } foreach и тому подобное - это круто! То же самое было бы намного сложнее в bash ...) вместо _ "все просто текст, используйте cut, sed, awk, grep, ..." _ беспорядок, который есть во всех оболочках, совместимых с POSIX!

@ Isti115 Основная проблема заключается в том, что инициализация управляемой среды выполнения значительно медленнее, чем
В репо также улучшена производительность. Я не думаю, что мы сможем добиться большего за это время.

Чит: вы можете создать и запустить простую бесконечную службу C # с помощью одной функции - загрузить все библиотеки DLL PowerShell.
(В результате все библиотеки DLL будут уже в памяти до того, как вы запустите PowerShell)
(Для службы вы также можете использовать PowerShell - запустить и Start-Sleep -Seconds 65535.)

Можно ли выполнить часть инициализации после запуска REPL?

  1. Инициализировать необходимый код для REPL
  2. После этого инициализируйте все остальное.

Я думаю, что REPL больше подходит для сценариев C #.
Для PowerShell есть идея хостинга от Джейсона, но, полагаю, ее нелегко реализовать.

Хм, читая все предложения, я пришел к идее простого сценария PowerShell, который непрерывно работает в фоновом режиме, считывая FIFO на входе и выполняя любые команды, которые туда передаются. Я знаю, что это очень запутанное решение, потому что переменные и контексты могут быть перепутаны, но если я буду достаточно осторожен при написании команд и убедитесь, что они не имеют побочных эффектов (я имею в виду, с точки зрения контекста выполнения, иначе это вообще не имело бы смысла запускать команды.: smile :) это могло бы сработать.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги