Улучшение скорости выполнения PowerShell - PullRequest
0 голосов
/ 25 августа 2018

Я поиграл с некоторыми алгоритмами сортировки, написанными в PowerShell вчера вечером. Предварительно мне пришлось сгенерировать массив случайных целочисленных значений, чтобы я мог что-то отсортировать. Однако время создания массива заняло у меня слишком много времени, поэтому я улучшил свой код, чтобы он работал максимально быстро.

Мой окончательный код выглядит так:

$max = 1000000
$RndNumberArr = New-Object System.Collections.ArrayList
$ran = New-Object Random
for ($i = 0; $i -lt $max; $i++)
{ 
    [void]$RndNumberArr.Add($ran.Next(0,$max))    
}

С помощью Measure-Command я получил среднее время выполнения около 2,5 с.

Я заметил, что использование ArrayList быстрее, чем использование массива с фиксированным размером (что не имеет большого смысла для меня, есть ли что-то быстрее?)

Кроме того, использование метода .NET random.Next() вместо CMDLet Get-Random также значительно улучшает скорость (сохраняется как 30 с).

Есть ли недостатки использования методов .NET?

Также я думаю, что используя

[void]$RndNumberArr.Add($ran.Next(0,$max)) 

для предотвращения вывода Array.Add немного быстрее, чем при использовании

$RndNumberArr.Add($ran.Next(0,$max)) > $null

Я прав?

CMDLet с четкой разницей во времени самый медленный.

$RndNumberArr.Add($ran.Next(0,$max)) | Out-Null

Влияет ли аппаратная часть моего компьютера (особенно ЦП) на скорость выполнения PowerShell или в какой-то момент скорость ограничена? Если да, есть ли способ увеличить назначенные системные ресурсы для повышения скорости?

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Полезный ответ TheIncorrigible1 предоставляет самое быстрое решение по двум причинам:

  • Позволяет PowerShell создать массив для вас, неявносбор всех выходных данных из цикла foreach.

  • Используется синтаксис диапазона в сочетании с foreach (1..$max), а не цикл for с арифметика ;в то время как цикл foreach с синтаксисом диапазона занимает больше памяти - массив индексов должен быть построен как единое целое - он заметно быстрее арифметического цикла for.


Я заметил, что использование ArrayList быстрее, чем использование Array с фиксированным размером

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

PowerShell скрывает этот факт от вас, позволяя вам делать $array += ..., но за кадром каждый раз создается массив new , включающийвсе оригинальные элементы плюс новый.Следовательно, в цикле с большим количеством итераций необходимо создавать новый массив на каждой итерации , что приводит к очень низкой производительности .

В этой проблеме GitHub предлагается потенциальное усовершенствование в будущем, позволяющее создавать по своей природе расширяемые списки PowerShell-идиоматическим способом.

Кроме того, я думаю, что использование [void]$RndNumberArr.Add($ran.Next(0,$max)) для предотвращения Array.Add вывод немного быстрее, чем при использовании $RndNumberArr.Add($ran.Next(0,$max)) > $null Я прав?

Да, с выводом из выражений [void] быстрее, хотя вы должны рассмотрите возможность использования столь же быстрого $null = ... вместо этого для синтаксического удобства , потому что = имеет наименьший приоритет оператора, поэтому вам не нужно беспокоиться о включении RHS в (...), в отличие от [void],учитывая, что приведение имеет высокий приоритет.


Есть ли недостатки использования .NET-методов?

Давайте установим upside first:

Возможность вызывать практически любые методы .NET-типа - это отличная функция расширяемости PowerShell - когда PowerShell не предоставляет функцию с помощью своих командлетов / функций иОПЕraters или не обеспечивает его достаточной производительности, обычно это делают методы .NET типов.

Тем не менее, есть недостатков :

  • Синтаксически, синтаксис метода ((...) вокруг списка аргументов, которые разделены ,) может вызвать путаницу с синтаксисом режима-команды (команды) PowerShell (как в оболочке: нет (...) вокруг аргументов, которые пропущены -разделены);Set-StrictMode -Version 2 или выше может помочь вам обнаружить непреднамеренные попытки вызова командлетов / функций PowerShell с синтаксисом метода.

  • В редких случаях возможно для новых перегрузок методов, представленных вболее поздние версии .NET Framework нарушают существующий код из-за природы поздней привязки PowerShell : если новые перегрузки приводят к тому, что существующий код связывается с ними, вещи могут сломаться.

  • Справкаметоды типов .NET не интегрированы с справочной системой PowerShell .


Влияет ли аппаратное обеспечение моего компьютера (особенно на ЦП) на скорость выполнения PowerShell илискорость ограничена в какой-то момент?Если да, есть ли способ увеличить назначенные системные ресурсы для повышения скорости?

Нет 1135 * регулирования использования процессора, о котором я знаю, но я могу 'Не говорите, если / как используются несколько процессоров / ядер - если кто-нибудь знает, сообщите нам.

Вообще говоря, , если подходит для данной задачи, распараллеливание может ускорить процесс, и есть несколько способов сделать это:

  • Использование фоновых заданий с Start-Job

  • В качестве более быстрой альтернативы используйте PowerShell SDK для создания нескольких пространств выполнения для каждого процесса, что предоставляет PoshRSJob модуль , предоставленный сообществом, в красиво упакованном, PowerShell - идиоматическая форма.

  • В Windows PowerShell рабочие процессы предлагают параллельное выполнение.

  • Наконец - снова, , если выполнимо для выполняемой задачи - вы можете распараллелить выполнение, распределив задачу по нескольким компьютерам с Invoke-Command.

0 голосов
/ 25 августа 2018

Если ваша цель - создать большой список случайных целых чисел, я бы рекомендовал вообще избегать управления списками:

$r = [Random]::new()
$max = 1000000
$list = foreach ($i in 1..$max)
{
    $r.Next(0, $max)
}

Этот код выполнялся почти вдвое быстрее по сравнению с использованием цикла for (примерно 1,4-1,5 секунды против 2,6 секунды).

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