Powershell добавляет многопоточность к готовому скрипту
Я получил scirpt, он работает нормально, но я хочу немного ускорить его, используя многопоточность. Проблема в том, что это довольно сложно сделать без изменения большого количества кода. Я хотел бы избежать работы с новыми разделенными областями, но похоже, что это невозможно. Кроме того, начальное задание выполняется очень медленно, для запуска требуется ~~150 миллисекунд. Есть ли способ избежать заданий или, по крайней мере, заставить этот скрипт работать, как и ожидалось? (нет дублированных функций, передавая аргументы правильно)
Param(
[int]$arg1 = 2, [int]$arg2 = 3
)
$functionDoSomething = {
function doSomething($inp) {
return $inp + 10
}
}
function doSomething($inp) {
return $inp + 10
}
# time: 1523337 ticks
Measure-Command {
Start-Job -Name Job1 -InitializationScript $functionDoSomething -ScriptBlock {
return doSomething ($arg1 + $arg2)
} -ArgumentList $arg1, $arg2
Wait-Job Job1
$var2 = Receive-Job Job1 # result is 10, so arguements aren't passed correctly, trick with @($arg1, arg2) = the same result
}
# time: 6867 ticks
Measure-Command {
$var3 = doSomething ($arg1 + $arg2) # result is 15
}
2 ответа
# Have no fear - Invoke-Parallel is here. Hoping that I can help steer you in the right direction. Let me show you some pseudo code that can point you in the right direction.
# You need a list of objects in which you want to perform an operation for
$listOfComputers = @(
'1'
'2'
'3'
)
# Pipe your array to Invoke-Parallel which takes care of opening threads depending on the amount of objects piped in.
# If you want to control the amount of simultaneous threads simply help Invoke-Parallel -ShowWindow to see how
$results = $listOfComputers | Invoke-Parallel -ScriptBlock {
function doSomething($inp)
{
return [int]$inp + 10
}
if ($_ -eq '1') { Start-Sleep -Seconds 15; Write-Verbose 'Waited 15s' } # Adding this so you can see that this script block is running in a multi-threaded fashion
# $_ refers to the values inside of $listOfComputers
return doSomething ($_)
} -Verbose
$results
<# Notice how 11 comes up last
12
13
11
#>
Сначала рассмотрим Runspaces и RunSpacePool. Когда вы создаете пространство выполнения, вы можете указать, какие модули загружаются, кроме стандартных. Смотрите здесь http://www.get-blog.com/?p=189 для более подробной информации.
$ScriptBlock = {
param([string]$forinput)
"Do something with $forinput"
[PSCusomObject]@{
Line1="Something"
Line2="Something done to $forinput"
}#end of custom object output
}#end script block
#Create Runspace pool, 100 min and max.
#Example data contained within $item.property
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(100,100)
$RunspacePool.Open()
$Jobs =
foreach ( $item in $VariableContainsListOfInput)
{
$Job = [powershell]::Create().
AddScript($ScriptBlock).
AddArgument($item.property)
$Job.RunspacePool = $RunspacePool
[PSCustomObject]@{
Pipe = $Job
Result = $Job.BeginInvoke()
}
}
DO{Start-sleep -seconds 1
}While($Jobs.Result.IsCompleted -contains $false)
#Loop through jobs, pipe EndInvoke data from runspace into Export-CSV
$(ForEach ($Job in $Jobs)
{ $Job.Pipe.EndInvoke($Job.Result) }) |
Export-Csv -Path "$FullPath\$file" -NoTypeInformation
#clean up runspace
$RunspacePool.Close()
$RunspacePool.Dispose()