Есть ли разница в эффективности между использованием конвейера и прямым использованием параметра InputObject? - PullRequest
0 голосов
/ 18 октября 2018

Вот пример, у меня есть удаленный сервер с именем "s1", и я хочу уничтожить в нем процессы calc, notepad, winword.

У меня может быть два способа сделать это,

  1. Использование конвейера

Get-Process -computername s1 -name "calc", "notepad", "winword" | Stop-Process

Использование параметра InputObject

$processes = Get-Process -computername s1 -name "calc", "notepad", "winword" Stop-Process -InputObject $processes

IMO, я думаю, что второй способ намного лучше первого.

Говорят, что конвейер в PowerShell фактически передает объект один за другим в следующий командлет.В этом случае Stop-Process необходимо связаться с удаленным компьютером "s1" много раз и убить эти процессы по одному.

В отличие от второго способа, я думаю, Stop-Процесс просто сообщит удаленному компьютеру "s1" один раз и завершит операцию одним выстрелом.

Я правильно понимаю?

Спасибо

Martin

1 Ответ

0 голосов
/ 18 октября 2018

Что касается удаленного аспекта :

Вам следует выбрать другой подход: запустить весь конвейер удаленно, используя 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 раз медленнее.

Однако обратите внимание, что факторы зависят от размера входного набора (и, возможно, вашего оборудования).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...