Улучшение производительности среды выполнения меньше ожидаемого - PullRequest
0 голосов
/ 19 октября 2018

Я профилирую некоторый код для производительности, но не получаю результатов от 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
...