2017-06-12 25 views
0

爲什麼在PowerShell中使用多線程非常慢,令人難以置信。我做錯了什麼?我正在使用PoshRsJob模塊。PoshRsJob性能問題

RSJobs:

(Measure-Command { 

    $output = Start-RSJob -InputObject $shortDump -ScriptBlock { 
     Param($out, $shortDump) 

     $retObj = [pscustomobject]@{ 
      UserMail = $_.Mail 
      Type = $_.Type 
     } 
     # return $retObj 
     $retObj 

    } | Wait-RSJob 

    $out.Add($(Get-RSJob | Receive-RSJob)) 
    # $out += $(Get-RSJob | Receive-RSJob) 

}).TotalSeconds 

標準foreach

(Measure-Command { 

    foreach ($obj in $shortDump) { 

     $retObj = [pscustomobject]@{ 
      UserMail =$obj.Mail 
      Type = $obj.Type 
     } 
     # $out+= $retObj 
     $out.Add($retObj) 
    } 
}).TotalSeconds 

我的目標是加快構建對象,因爲我有〜300.000對象來構建。

編輯:這是另一個例子。這非常慢!

快速

$out = New-Object System.Collections.ArrayList 
"default" 
(Measure-Command { 

    for ($x = 0; $x -lt 100000; $x++) 
    { 

     $retObj = [pscustomobject]@{ 
      UserMail = 'test' 
      Type = 'test2' 
      Test = 'default' 
     } 
     $out.Add($retObj) 
    } 

}).TotalSeconds 
$out2 = $out 

可怕的慢

$out = New-Object System.Collections.ArrayList 
$Test = `"RSJobs"` 
"RSJobs" 

$ScriptBlock = {  

[pscustomobject]@{ 
    UserMail = 'test' 
    Type = 'test2' 
    Test = $Using:Test 
} 
} 

(Measure-Command { 
    1..100000 | Start-RSJob -Name {$_} -ScriptBlock $ScriptBlock 
    $out.Add($(Get-RSJob | Receive-RSJob)) 

}).TotalSeconds 
+0

測試中輸入大小有多大?另外,可能包含'TotalSeconds'結果作爲參考 –

+0

輸入大小是一個包含10.000個對象的數組。區別在於: RSJobs: 106,0617351秒 標準foreach: 0,3592102秒 – CaspervanDoorn

+0

看起來像RSJobs代碼是不完整的(並非所有的變量都考慮在內)等等。你能提供一個MVCE(https://stackoverflow.com/help/mcve)嗎?與此同時,我注意到PostRsJobs的博客強調你不應該將'Start-RSJob'放在foreach循環中,否則你將會爲循環中的每個項目組裝新的運行空間池。 –

回答

0

創建一個新的運行空間有開銷。因此,對於許多小型工作,您每次都會增加開銷。

(measure-command {[pscustomobject]@{'a'='b'}}).totalmilliseconds 
0.1773 

{start-rsjob -scriptblock {[pscustomobject]@{'a'='b'}}}).totalmilliseconds 
93.0173 

然後你添加更多的開銷檢索所有來自各個作業返回的數據整合到一個對象,它基本上是擺在首位你的目標。

基本上,從100,000個對象中構建1個對象vs創建一個運行空間100,000次,每個創建1個對象然後返回所有這些對象以從100,000個對象構建1個對象。

我不明白你將如何在這個應用程序中使用運行空間獲得任何效率的增益。如果確定每個對象需要昂貴的計算,然後你只做了幾個運行空間並在每個運行空間中運行一個數組的子集,或許。

+0

「如果確定每個對象需要昂貴的計算,然後您只做了幾個運行空間並在每個運行空間中運行了一個數組的子集,也許。 我明白。是的,在創建新對象之前,必須滿足許多條件。我會檢查這一點。謝謝 (measure-command {start-rsjob -scriptblock {[pscustomobject] @ {'a'='b'}}})。totalmilliseconds 最後一個問題:是否有其他解決方案可以更快地在PowerShell中創建對象使用作業或運行空間。 – CaspervanDoorn

+0

@CaspervanDoorn Runspaces是我知道的最低並行開銷方法。還有工作流程,但我不認爲並行是你的魔力子彈....雖然運行空間不是對象創建的,但是'[pscustomobject]'是最有效的'New-Object'或'Select-Object'。 – BenH