0

非常に大規模なサーバーで使用するために、次のコードを高速化する方法が必要です。必要なのはフルネーム パラメータのリストだけです。次のようなものを使用したいと思います: http://newsqlblog.com/2012/05/22/concurrency-in-powershell-multi-threading-with-runspaces/

私はそれについて読んでいましたが、それは非常に単純に思えますが、スレッドが既存のプールに新しいスレッドを作成できるようにすること、およびそのプールを渡す方法について頭を悩ませることはできません。

これの速度はひどいものであり、私が利用しているよりもはるかに多くのリソースがあるため、どんな助けも素晴らしいでしょう.

Function Get-ChildItemToDepth {   
    Param(     
        [String]$Path = $PWD,    
        [int]$ToDepth = 255,     
        [Byte]$CurrentDepth = 0
    ) 
    if ($ToDepth -lt 0) {
        return get-item $path
    }
    $CurrentDepth++
    Get-ChildItem $Path | Where-Object { $_.PSIsContainer } | %{ $_ 
        If ($CurrentDepth -le $ToDepth) {
            Get-ChildItemToDepth -Path $_.FullName `
            -ToDepth $ToDepth -CurrentDepth $CurrentDepth
        } 
    }
}   

注: v2.0 に制限されています

概要: 私は基本的に、$depth までのすべてのフォルダーへのパスを、デジタル的に可能な限り高速に配列に入れる必要があります。

悲惨な失敗の試み:

$func = `
{
    Param(     
        [String]$Path = $PWD,    
        [int]$ToDepth = 255,     
        [Byte]$CurrentDepth = 0,
        $p = $pool
    ) 
    if ($ToDepth -lt 0) {
        return $path
    }
    $CurrentDepth++
    $folders = Get-ChildItem $Path | Where-Object { $_.PSIsContainer } | select -expand FullName
    If ($CurrentDepth -le $ToDepth) {
        foreach ($path in $folders) {
            $pipeline  = [System.Management.Automation.PowerShell]::create()  
            $pipeline.RunspacePool = $pool 
            $pipeline.AddScript($func).AddArgument($path).AddArgument($ToDepth).AddArgument($CurrentDepth).AddArgument($pool)
            $AsyncHandle = $pipeline.BeginInvoke() 
            $folders += $pipeline.EndInvoke($AsyncHandle)  
            $pipeline.Dispose()  
        }
    }
    return $folders
}    

$path = "\\server\users-folder\"
$toDepth = 3

$pool = [RunspaceFactory]::CreateRunspacePool(1, 4) 
$pool.ApartmentState = "STA" 
$pool.Open() 
$pipeline  = [System.Management.Automation.PowerShell]::create()  
$pipeline.RunspacePool = $pool  
$pipeline.AddScript($func).AddArgument($path).AddArgument($toDepth).AddArgument($CurrentDepth).AddArgument($pool)
$AsyncHandle = $pipeline.BeginInvoke() 
$RESULTS = $pipeline.EndInvoke($AsyncHandle)  
$pipeline.Dispose()  
$pool.Close()
4

2 に答える 2

1

ワークフローでこれを呼び出してみてください - PowerShell 3.0 ですぐに利用できる強力なネイティブ PowerShell マルチスレッド ソリューション

Workflow Invoke-Function
{
Function Get-ChildItemToDepth {   
    Param(     
        [String]$Path = $PWD,    
        [int]$ToDepth = 255,     
        [Byte]$CurrentDepth = 0
    ) 
    if ($ToDepth -lt 0) {
        return $path
    }
    $CurrentDepth++
    Get-ChildItem $Path | Where-Object { $_.PSIsContainer } | %{ $_ 
        If ($CurrentDepth -le $ToDepth) {
            Get-ChildItemToDepth -Path $_.FullName `
            -ToDepth $ToDepth -CurrentDepth $CurrentDepth
        } 
    }
}  
Get-ChildItemToDepth 
}

これはかなり厄介な実装です。関数と呼び出しをワークフローにラップしただけなので、テストを簡単にするためにセッションにコピーアンドペーストできます。それがどのように機能するか教えてください。速度の違いを確認したい場合は、関数の結果を Measure にパイプします

Get-ChildItemToDepth | Measure
Invoke-Function | Measure

使用法 (ワークフローをセッションに貼り付けた後)

Invoke-Function
于 2013-02-25T19:29:16.743 に答える
0

http://psasync.codeplex.comに移動し、psasync モジュールをダウンロードします (ドキュメントはこちらhttp://newsqlblog.com/2012/12/17/psasync-module-multithreaded-powershell/ )。それで ...

Import-Module psasync

$AsyncPipelines = @()

# Allow 4 concurrent processes ... adjust up / down as hardware allows
$pool = Get-RunspacePool 4

# You can play with this to get better performance by going deeper into the directory structure to populate more dirs in the array
# gross generalization -> more dirs + more runspaces in $pool = faster performance

$rootDirs = Get-ChildItem c:\ | Where-Object{$_.PSIsContainer}

# Create a script block to run code per directory stored in $rootDirs
$ScriptBlock =  { ` 
    Param(     
        [String]$Path = $path
    ) 
    Get-ChildItem $path -recurse | Where-Object{$_.PSIsContainer}

}   

# Load up processes on the runspace pool
foreach($dir in $rootDirs) {
    $AsyncPipelines += Invoke-Async -RunspacePool $pool -ScriptBlock $ScriptBlock -Parameters $dir.FullName
}

# "Listen" to the pipelines and grab the results
$dirs = Receive-AsyncResults -Pipelines $AsyncPipelines

# PROFIT
$dirs | Foreach-Object{$_.FullName}

そして、newsqlblog.com を読んでくれてありがとう ;)

于 2013-02-27T00:35:55.260 に答える