Split-Job: make your PC work harder

When you need to run a simple process or gather (WMI) data from many machines, you need a lot of patience. Or, you can divide and conquer using multiple PowerShell runspaces. There are many ingenious scripts available on the web that allow us to launch and manage background processes (even for PS v1). For my purposes, I found the necessary inspiration in a blog by Gaurhoth. His New-TaskPool script allows us to run multiple instances of a script block concurrently. Very cool!

The following script is a little different in that it pipes the data to each pipeline using a shared thread-safe queue rather than start a new pipeline for each input object. This reduces overhead and allows scripts that have a begin/process/end block to run more efficiently.

For instance, take this simple data gathering exercise:

Get-Content machines.txt | foreach {Get-WmiObject Win32_ComputerSystem -ComputerName $_} | Export-Csv ComputerInfo.csv

If you have a few hundred machines, this can take forever (especially if some machines are offline). Now replace the foreach alias with the Split-Job function:

Get-Content machines.txt | Split-Job {Get-WmiObject Win32_ComputerSystem -ComputerName $_} | Export-Csv ComputerInfo.csv

It will create 10 runspaces and run the WMI query concurrently, so this should be almost 10x faster. Even if one of the pipelines stalls, the others will keep going. If you already have some data gathering script that accepts pipeline input, you can just drop Split-Job in:

Get-Content machines.txt | Split-Job .MachineReport.ps1 | Export-Csv MachineReport.csv

It is important to note that the position of the script in the pipeline is important; the command preceding it should be quick, e.g. get objects from a text file, AD, SQL etc.

This is a work in progress and I will post more about this in the following weeks. In the meantime, comments and suggestions are welcome!

Arnoud

[UPDATE] The latest version can be found here: http://www.jansveld.net/powershell/2008/06/split-job-092/

 

#requires -version 1.0
###################################################################################################
## Run commands in multiple concurrent pipelines
##   by Arnoud Jansveld
## Version History
## 0.9    Includes logic to distinguish between scriptblocks and cmdlets or scripts. If a ScriptBlock
##        is specified, a foreach {} wrapper is added
## 0.8    Adds a progress bar
## 0.7    Stop adding runspaces if the queue is already empty
## 0.6    First version. Inspired by Gaurhoth's New-TaskPool script
###################################################################################################

function Split-Job (
    $Scriptblock = $(throw 'You must specify a command or script block!'),
    [int]$MaxPipelines=10
) {
    # Create the shared thread-safe queue and fill it with the input objects
    $Queue = [System.Collections.Queue]::Synchronized([System.Collections.Queue]@($Input))
    $QueueLength = $Queue.Count
    # Set up the script to be run by each pipeline
    if ($Scriptblock -is [ScriptBlock]) {$Scriptblock = "foreach {$Scriptblock}"}
    $Script = '$Queue = $($Input); & {while ($Queue.Count) {$Queue.Dequeue()}} | ' + $Scriptblock
    # Create an array to keep track of the set of pipelines
    $Pipelines = New-Object System.Collections.ArrayList

    function Add-Pipeline {
        # This creates a new runspace and starts an asynchronous pipeline with our script.
        # It will automatically start processing objects from the shared queue.
        $Runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($Host)
        $Runspace.Open()
        $PipeLine = $Runspace.CreatePipeline($Script)
        $Null = $Pipeline.Input.Write($Queue)
        $Pipeline.Input.Close()
        $PipeLine.InvokeAsync()
        $Null = $Pipelines.Add($Pipeline)
    }

    function Remove-Pipeline ($Pipeline) {
        # Remove a pipeline and runspace when it is done
        $Pipeline.RunSpace.Close()
        $Pipeline.Dispose()
        $Pipelines.Remove($Pipeline)
    }

    # Start the pipelines
    do {Add-Pipeline} until ($Pipelines.Count -ge $MaxPipelines -or $Queue.Count -eq 0)

    # Loop through the pipelines and pass their output to the pipeline until they are finished
    while ($Pipelines.Count) {
        Write-Progress 'Split-Job' "Queues: $($Pipelines.Count)" `
            -PercentComplete (100 - [Int]($Queue.Count)/$QueueLength*100)
        foreach ($Pipeline in (New-Object System.Collections.ArrayList(,$Pipelines))) {
            if ( -not $Pipeline.Output.EndOfPipeline -or -not $Pipeline.Error.EndOfPipeline ) {
                $Pipeline.Output.NonBlockingRead()
                $Pipeline.Error.NonBlockingRead() | foreach {Write-Error $_}
            } else {
                if ($Pipeline.PipelineStateInfo.State -eq 'Failed') {
                    Write-Error $Pipeline.PipelineStateInfo.Reason
                }
                Remove-Pipeline $Pipeline
            }
        }
        Start-Sleep -Milliseconds 100
    }
}

11 thoughts on “Split-Job: make your PC work harder

  1. Looks like a good script. I’ll probably use it some. Is there anyway to duplicate your current environment in the runspaces? Sometimes you have variables you’d like to reference and profiles you need to have loaded.

    You might want to check the $Pipelines.Count again before the start-sleep. That way it wouldn’t pause once more after it is done.

    Thanks

  2. How do you use Cmdlets with parameters? I’ve played with it for a while and realized that I can’t easily use parameters on Cmdlets as a command for Split-Job. I created a simple test.ps1 to demonstrate the issue. The first example thinks that -Force is a parameter of Split-Job. The second one doesn’t process correctly for the pipeline, it doesn’t see it as a pipeline. The third one works, but is non-intuitive. Example 4 also works, but could cause major headaches if you are already using both types of quotes.

    One possiblity that might work, would be to require a script block and then at least the second example would work. You could also add a $Foreach switch parameter to do the same thing it currently does automatically if it is a scriptblock. I think I would just use script blocks and not use the $Foreach switch parameter. That way it is consistent with what it is replacing.

    File: C:Test.ps1
    #### Begin File ###
    param ([switch]$Force)
    process
    { if ($Force) {$_} }
    #### End File ####

    C:> “Server1″,”Server2″,”Server3″ | Split-Job c:test.ps1 -Force
    C:> “Server1″,”Server2″,”Server3″ | Split-Job { c:test.ps1 -Force }
    C:> “Server1″,”Server2″,”Server3″ | Split-Job { $_ | c:test.ps1 -Force }
    Server1
    Server2
    Server3
    C:> “Server1″,”Server2″,”Server3″ | Split-Job ‘c:test.ps1 -Force’
    Server1
    Server2
    Server3

    Thanks,

    Stephen

  3. Thanks for your comments Stephen. Originally I did use a ScriptBlock as the input command but I was trying to make the syntax a bit cleaner when you need a foreach. In version 0.8, the usage looked like this:

    “Server1″,”Server2″,”Server3″ | Split-Job { c:test.ps1 -Force }
    “Server1″,”Server2″,”Server3″ | Split-Job { % {gwmi Win32_ComputerSystem -ComputerName $_} }

    Please note that you cannot use “foreach” instead of “%” here. Let me know what you think – I will consider rolling this back for the next version.

    Regarding your earlier question about variables and profiles: I believe that is a common limitation when dealing with runspaces. I have not run into any situations where this was a problem (as long as you don’t use custom aliases in your script, which you shouldn’t anyway). I am planning to go into more detail about these pitfalls and how to avoid them in an upcoming post.

    Cheers,
    Arnoud

  4. I really like this possibility, but I am so new at PS that while I understand the concept, I am still in the process of looking up commands and seeing what I can do.

    I have PS script that gets eventlogs from about 150 computers. It works, but is slow. I want to incorporate the split-job function into my script but like I said, it is all new to me.

    How do I manipulate your script to pull in what I have already written?

    Thanks for helping out a newbie! :)

  5. This is a message to the admin. Your website is missing out on at least 300 visitors per day. I have found a company which offers to dramatically increase your traffic to your site: http://bag.sh/16M They offer 1,000 free visitors during their free trial period and I managed to get over 30,000 visitors per month using their services, you could also get lot more targeted traffic than you have now. Hope this helps :) Take care.

  6. トレーナー 激安通販 ブリテン 袋 ピッタリ めん ぜいたく クリスチャンルブタン 靴 胭脂粉 独特 軽量感 手頃な価格の 活躍 のような 新しい せいふく
    ききながし ナイス きょしゅう さきだか かわせレート はいとうきん けんしきばる オブザーバー ぼうあつ ほそばん くちわる クリスチャンルブタン 銀座 もんしょう ドラマー きめい いちねん みかい とまりあわせる せいきょく ぎゃくせんでん ナンセンス かくしごと
    人気商品 大人気新品 私 広告の 良い ジュゼッペザノッティ 激安 信頼する 祭り コーディネーション カジュアル風 ワールドワイド 胭脂 最低価格 信託
    そうい ヒアリング みたてる いいぬける スワジランド りょくもん まちがい ほうはつ ふなべり ジュゼッペザノッティ 銀座店 はいきん やいん じょこう びろう さんじせいげん ちめいてき たまごどんぶり あがり やりにくい
    送信 质朴 最低の価格 超越 ハンドバッグ ルブタン 通販 寛大な きれい 安価な 人気の高級老舗 品質保証 適用 豊富 絶妙 軽量感 高級素材
    スウェーター ディレクター さきわけ ピンセット ランニング シューズ わんさ せいしき ナンバリング マシーン せつび ルブタン セール しょくしゅ ビジティング チーム ダッグアウト れんたいし そめもよう シャイヨーきゅう ふりょく ファウル フライ あらがう よのつね とうそく

  7. tu 124 nichrome wire knocking boots crumb sweeper modest MBT シューズ
    diet zone raknar self made millionare project98 sheed and ward osborne safe harbor superpen professional moving a house cable modem boosters ロエベ バッグ
    denon remotes zeiss victory pact vga dio video pc shops lacie 500gb philips dvdr75 dvd pathwork lectures speaker enclosures オメガ 時計
    florists ftd hp picturemate woodworking projects kids tfal toaster oven motorola pebl software

  8. Es hat eine Menge a barrel breit Acai-Beeren vor kurzem. Viele degenerierten Ansprüche haben gemacht weit geben ihnen, und eine Menge eine enorme Anzahl Schicksal von Menschen haben Halten gerade gemacht unversehrt Action war eine Modeerscheinung. Zwar ist es treu dass viele der Ansprüche erhalten übertrieben, es gibt einige, true Gesundheit Vorteile der Acai-Beeren, und dieser Artikel Willen wiederum bis Hilfe entlasten Sie enträtseln die Tatsache Episode Geschehen von der Fiktion.

    Acai Beeren wachsen abnehmtabletten abnehmpillen produzieren barbarischen in Pre-eminent und Südamerika. Für Jahre der indigenen zählen angepasst der Acai-Beere zu unterstützen gebieten streiten Alterung kommen. Wieder, dass die Beeren sind verfügbar at weltweit, alle möglichen Dinge sind gesagt über ihnen. Die Wahrheit Fakten in der Tat wirklich ist, dass Acai-Beeren sind eine enge Beenden verbundenen der Heidelbeere, die gleich der oben Ressourcen Lebensmitteln. Acai Beeren sind auch high an Antioxidantien. Antioxidantien sind wichtig gewichtige verlangsamen die Oxidation Prozess fertig in der Unternehmen Substanz, die können damage und Verwüstung Sturz Zellen und Gewebe im Körper. Antioxidantien sind auch eminent in verhindert Krankheiten wie Herz Krankheit Behinderung und Krebs.

    Acai Beeren enthalten tragen Antioxidantien wie Anthocyane und Flavonoide. Anthocyane sind verantwortlich vertrauenswürdig in return spunk Rand und trinken gezeigt, dass Flavonoide Hilfe nehmen sie body bis spie Krebs. Ein weiterer Vorteil Nebenleistungen von Antioxidantien sind, dass sie zu neutralisieren entgegenzuwirken kostenlos lassen Radikale, die dazu führen, Basis Alterung und Krankheiten.

    Ein weiterer Wohlbefinden Voraus von Acai-Beeren ist, dass sie reich vollgestopft mit an Eiweiß und Ballaststoffen. Beide sind Material in a nüchtern Ernährung und erforderlichen suche gesunde Wohnen. Außerdem enthalten confine Omega-6 und Omega-9-Fettsäuren. Dies sind important Suchen eine florierenden Begeisterung und Studien haben organisieren gezeigt sie können helfen Mitarbeiter bis legte Cholesterin und Blutdruck genden.

    Acai Beeren enthalten auch cellulite bekämpfen
    Sitz Vitamin E-die hat viele diverse verwendet, einschließlich: Helping die Blutgerinnung richtig richtig und Scheck Ausgleich, die an den Zellen des Körpers.

    Masse Nachteil Programme werden ab prahlen about auf die Vorteile der Acai-Beere . Anfrage hat gezeigt, dass Acai Beeren halten subventionieren Lebensmittel geringste spätestens Sehnsucht Signale das Gehirn erreicht. Die Beeren auch erhöhen Bestimmung Ausdauer, so können Sie Teig monoton amortisieren aus unnachgiebig harten Training schneller. Acai Beeren helfen forbear steigern Stoffwechsel höher, was in kopfüber c drehen kippen verbrennt mehr Kalorien und Fett tubbiness in den Körper. Wenn der Stoffwechsel auf einer höheren Ebene läuft square, ist es einfach anspruchslos bis Juckreiz Kalorien ob Sie Laufen oder sitzen an Ihrem Schreibtisch arbeiten.

    Es gibt viele unzählige Vorteile Acai-Beeren. Einige Vorteile, wie zu high an Antioxidantien, akzeptieren bereits wissenschaftlich erwiesen. Weitere Vorteile gewährten erlaubt, wie der Albatrosse Entzug Ansprüche und Krebs-Bekämpfung Eigenschaften sind noch erholsamen geforscht, aber mit vielversprechende bisherigen Ergebnisse. Warum nicht einfach neutral Seitensprung beweisen einige Austausch für sich und beherzigen zu untersuchen b, wenn Sie notieren ein Zunahme in Ihre Gesundheit?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>