Что касается удаленного аспекта :
Вам следует выбрать другой подход: запустить весь конвейер удаленно, используя Invoke-Command
:
Invoke-Command -ComputerName s1 {
Get-Process -Name 'calc', 'notepad', 'winword' | Stop-Process
}
Обратите внимание, однако, что Invoke-Command
(PSv3 +) требует, чтобы PowerShell Remoting был настроен на целевой машине (см. Get-Help about_Remote_FAQ
), тогда как командлет Get-Process
использует другую, устаревшую форму удаленного взаимодействия.
Фактически, когда я попробовал ваш подход между двумя машинами v5.1, локально запущенная команда Stop-Process
, которая пыталась работать с удаленными объектами процесса , не смогла , со следующей ошибкой:
Cannot stop process "<name>" because of the following error:
Feature is not supported for remote machines.
Как правило, лучше всего выполнить как можно больше удаленной обработки и передать результаты только на локальный компьютер .
Что касаетсябольше общий аспект ввода конвейера по сравнению с вводом через -InputObject
:
Использование -InputObject
для передачи коллекции (Get-Foo -InputObject $collection
) определенно быстрее , чемотправляя эту коллекцию по конвейеру ($collection | Get-Foo
), но учтите, что требует, чтобы вся входная коллекция была загружена в память в целом , вперед , что потенциально сводит на нет ключевое преимущество конвейера: регулирование памяти.
Обратите внимание, что использование -InputObject
часто не жизнеспособная альтернатива вводу конвейера , потому чтомногие командлеты не перечисляют coвыборы, которые вы передаете -InputObject
(сравните 1, 2 | ForEach-Object { "[$_]" }
с ForEach-Object { "[$_]" } -InputObject 1, 2
);как правило, это происходит случайно, с объявлениями -InputObject
, которые не являются массивами , но иногда это так: командлет Get-Member
намеренно не перечисляет коллекцию, переданную в -InputObject
, потому что онзатем проверяет тип коллекции *1064*, а не ее элементы.См. эту проблему GitHub для получения справочной информации.
Также обратите внимание, что если есть дополнительные сегменты конвейера (Get-Foo -InputObject ... | ...
), то потоковая передача (обработка по одной) снова происходит на выходе .
Вы можете ускорить постатейную обработку, используя оператор foreach
(foreach ($elem in $collection) { ... }
) вместоконвейер, но это эффективно только , если вы можете избежать вызовов командлетов в теле цикла .
Как и в случае -InputObject
, однако, для этого требуется, чтобы вся входная коллекция была загружена в память в целом , впереди
Сравнение производительности с 10 000 входных объектов, усредненное по 100 прогонам, с использованием Time-Command
:
$collection = 1..10000
Time-Command -Count 100 { $collection | Write-Output },
{ Write-Output -InputObject $collection },
{ foreach ($o in $collection) { $o } }
Пример времени (Windows PowerShell 5.1 в Windows 10, одноядерная виртуальная машина):
Command Secs (100-run avg.) TimeSpan Factor
------- ------------------- -------- ------
foreach ($o in $collection) { $o } 0.010 00:00:00.0103421 1.00
Write-Output -InputObject $collection 0.015 00:00:00.0152200 1.47
$collection | Write-Output 0.108 00:00:00.1076183 10.41
foreach
самый быстрый (обратите внимание, как неявный вывод используется в теле цикла: если бы использовался вызов Write-Output
, это было бы самым медленным решениемn) с показателями -InputObject
не сильно отстали;Интересно, что в PowerShell роли поменялись местами Core . - Обеспечение ввода через конвейер было примерно в 10 раз медленнее.
Однако обратите внимание, что факторы зависят от размера входного набора (и, возможно, вашего оборудования).