Я профилирую некоторый код для производительности, но не получаю результатов от Runspaces, как я ожидал.
Мои исходные файлы - это 7 файлов журнала Autodesk Revit, размер которых варьируется от 13 МБ и 150 КБ до 90 МБ и 900 КБ.Каждый файл содержит ссылку на собственное имя несколько раз, поэтому я получаю этот счет в качестве прокси для какой-то реальной работы, которую я хочу сделать позже.В приведенном ниже коде я обрабатываю все файлы с помощью простого foreach, а затем снова использую пространства выполнения, ограниченные до 8. В обоих случаях я использую потоковое считывающее устройство для разбора файлов, так как файлы могут быть намного больше, чем те, которые я тестируюс.Я не ожидал бы, что пример пространства выполнения будет 25% времени цикла, но я, конечно, ожидал бы, что он будет ближе к 25%, чем даже к 50%.Вместо этого я вижу улучшение менее чем на 50%.Последний запуск составил 14,26 секунды для одного потока и 8,74 секунды для 8 пространств выполнения.Я делаю что-то не так в своем коде, или мои ожидания неверны?FWIW Я сейчас тестирую на ВМ.Я попытался назначить 4, 6, 8 и 12 ядер для виртуальной машины с небольшой разницей в результатах.В этом последнем тесте было назначено 12 ядер, а количество рабочих мест уменьшено до 8. Это с 10-ядерным гиперпоточным Xeon на хост-компьютере.
РЕДАКТИРОВАТЬ: я изменил код, чтобы скопировать файлы ресурсов в temp, чтобы удалить сетьпеременная, и я добавил тест на основе заданий, снова ограниченный теми же 8 одновременными потоками, в которые заданы пространства выполнения.Время в соответствии с 16,8 против 9,6 против 7,3.Итак, рабочие места неизменно лучше, хотя, насколько я понимаю, пространства выполнения более эффективны и должны быть быстрее, и при этом производительность едва ли лучше, чем 50% -ная экономия, даже с 8 потоками.
$source = '\\Px\Support\Profiling\Source'
$localSource = "$env:TEMP\Px"
Clear-Host
if (Test-Path $localSource) {
Remove-Item "$localSource\*" -Recurse -force
} else {
New-Item $localSource -ItemType:Directory > $null
}
Copy-Item "$source\*" $localSource
$journals = Get-ChildItem $localSource
Write-Host "Single Thread"
(Measure-Command {
foreach ($journal in $journals) {
$count = 0
#$reader = [IO.StreamReader]::New($journal.fullName, $true)
$reader = New-Object -typeName:System.IO.StreamReader -argumentList $journal.fullName
while (-not ($reader.EndOfStream)) {
$line = ($reader.ReadLine()).Trim()
if ($line -match $journal) {
$count ++
}
}
Write-Host "$journal $count"
$reader.Close()
$reader.Dispose()
}
}).totalSeconds
Write-Host
Write-Host "Runspace 1,8"
(Measure-Command {
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1,8)
$runspacePool.Open()
$runspaceCollection = New-Object system.collections.arraylist
$scriptBlock = {
param (
[string]$journal
)
$journalName = Split-Path $journal -leaf
$count = 0
#$reader = [IO.StreamReader]::New($journal, $true)
$reader = New-Object -typeName:System.IO.StreamReader -argumentList $journal
while (-not ($reader.EndOfStream)) {
$line = ($reader.ReadLine()).Trim()
if ($line -match $journalName) {
$count ++
}
}
$reader.Close()
$reader.Dispose()
"$journalName $count"
}
foreach ($journal in $journals) {
$parameters = @{
journal = $journal.fullName
}
$powershell = [PowerShell]::Create()
$powershell.RunspacePool = $RunspacePool
$powershell.AddScript($scriptBlock) > $null
$powershell.AddParameters($parameters) > $null
$runspace = New-Object -TypeName PSObject -Property @{
runspace = $powershell.BeginInvoke()
powerShell = $powershell
}
$runspaceCollection.Add($runspace) > $null
}
while($runspaceCollection){
foreach($runspace in $runspaceCollection.ToArray()){
if($runspace.RunSpace.IsCompleted -eq $true){
Write-Host "$($runspace.Powershell.EndInvoke($runspace.RunSpace))"
$runspace.Powershell.dispose()
$runspaceCollection.Remove($runspace)
#[System.GC]::Collect()
Start-Sleep -m:100
}
}
}
}).totalSeconds
Write-Host
Write-Host "Jobs 8"
Remove-Job *
(Measure-Command {
$scriptBlock = {
param (
[string]$journal
)
$journalName = Split-Path $journal -leaf
$count = 0
#$reader = [IO.StreamReader]::New($journal, $true)
$reader = New-Object -typeName:System.IO.StreamReader -argumentList:$journal
while (-not ($reader.EndOfStream)) {
$line = ($reader.ReadLine()).Trim()
if ($line -match $journalName) {
$count ++
}
}
$reader.Close()
$reader.Dispose()
Write-Output "$journalName $count"
}
foreach ($journal in $journals) {
Start-Job -ScriptBlock:$scriptBlock -argumentlist:$journal.fullName
While($(Get-Job -State 'Running').Count -ge 8) {
sleep -m:100
}
}
Get-Job | Wait-Job
foreach ($job in Get-Job) {
Write-Host "$(Receive-Job $job)"
Remove-Job $job
}
}).totalSeconds
Write-Host
Remove-Item $localSource -Recurse -force