Invoke-Command быстрее, чем сама команда?

Я пытался измерить некоторые способы записи в файлы в PowerShell. Нет сомнений, но я не понимаю, почему первый Measure-Command Оператор ниже занимает больше времени, чем второй оператор.

Они одинаковые, но во втором я пишу скрипт-блок для отправки Invoke-Command а в первом я только запускаю команду.

Вся информация о Invoke-Command скорость я могу найти о удаленном

Этот блок занимает около 4 секунд:

Measure-Command {
    $stream = [System.IO.StreamWriter] "$PSScriptRoot\t.txt"
    $i = 0
    while ($i -le 1000000) {
        $stream.WriteLine("This is the line number: $i")
        $i++
    }
    $stream.Close() 
} # takes 4 sec

И этот код ниже, который точно такой же, но написан в блоке сценария, передан Invoke-Command занимает около 1 секунды:

Measure-Command {
    $cmdtest = {
        $stream = [System.IO.StreamWriter] "$PSScriptRoot\t2.txt"
        $i = 0
        while ($i -le 1000000) {
            $stream.WriteLine("This is the line number: $i")
            $i++
        }
        $stream.Close()
     }
     Invoke-Command -ScriptBlock $cmdtest
} # Takes 1 second

Как это возможно?

0 ответов

Как выясняется, основываясь на отзывах члена команды PowerShell по этой связанной проблеме GitHub, проблема в целом заключается в (неявном) точечном источнике (таком как прямой вызов выражения) по сравнению с выполнением в дочерней области, такой как с &, оператор вызова, или, в данном случае, с Invoke-Command -ScriptBlock,

Запуск в дочерней области избегает поиска переменных, которые выполняются при (неявном) точечном источнике.

Поэтому, начиная с Windows PowerShell v5.1 / PowerShell Core 6.2, вы можете ускорить выражения без побочных эффектов, просто вызывая их через & { ... } в дочерней области (несколько нелогично, учитывая, что создание новой области требует дополнительной работы):

То есть эта оптимизация может использоваться с выражениями, которые не должны изменять переменные вызывающего (напрямую).

Следующий упрощенный код, который использует foreach выражение для цикла 1 миллион раз (1e6) демонстрирует это:

# REGULAR, direct invocation of an expression (a `foreach` statement in this case), 
# which is implicitly DOT-SOURCED
(Measure-Command { $result = foreach ($n in 1..1e6) { $n } }).TotalSeconds

# OPTIMIZED invocation in CHILD SCOPE, using & { ... }
# 10+ TIMES FASTER.
(Measure-Command { $result = & { foreach ($n in 1..1e6) { $n } } }).TotalSeconds
Другие вопросы по тегам