none
PS: фоновые задания тормозят RRS feed

  • Вопрос

  • Ниже код, в который после добавления Job, время выполнения вместо уменьшения, наоборот увеличилось в несколько раз. 
    Кто по PowerShell спец, подскажите в чем причина замедления, вместо ускорения? 
    Т.е. блок скрипта $scr ранее был вместо строчки Start-Job и все выполнялось последовательно в течении 4 часов. После того, как сделал, как сейчас в коде, то время выполнения в р-не 10 часов и еще выполнялся в процессе... 

    $scr = { 
    param($s,$d) 
          
          if (Test-Path $d) 
          { 
           robocopy $s $d 
          }else 
          { 
            
             New-Item -Path $d -type directory -Force 
             robocopy $s $d 
            
          } 



    foreach($uwhois in $Catalog) 

     foreach($c in $Computers) 
     { 
       $source = '\\{0}\C$\Documents and Settings\{1}' -f $Server,$uwhois 
       $dest = '\\{0}\C$\Documents and Settings\{1}' -f $c,$uwhois 
       Start-Job -Name $uwhois -ScriptBlock $scr -ArgumentList ($source,$dest) 
     } 
     Get-Job | Wait-Job 
     Get-Job | Remove-Job 
    }

    12 марта 2015 г. 8:21

Ответы

  • Почему нормальное?  - Robocopy утилизирует все доступную полосу пропускания, тут создается несколько потоков, которые ведут борьбу за эту полосу и чем их больше, тем больше время на обслуживания пустых и ненужных операций.

    Если производительность жестких дисков и сетевой подсистемы сервера позволяет, то следует исправить код:

    1) Объединить все каталоги для 1 компьютера в один Job

    $scr = { 
    	param($catalog,$c,$Server = "server.contoso.com") 
        
    	foreach($uwhois in $Catalog) 
    	{ 
    		$s = '\\{0}\C$\Documents and Settings\{1}' -f $Server,$uwhois 
    		$d = '\\{0}\C$\Documents and Settings\{1}' -f $c,$uwhois 
    		
    		if (!(Test-Path $d)) 
    		{ 
    			New-Item -Path $d -type directory -Force 
    		}  
    		robocopy $s $d 
    	}
    
     } 
    
     
    foreach($c in $Computers) 
    { 
    	Start-Job -Name $c -ScriptBlock $scr -ArgumentList $Catalog,$c
    } 

    2) Посчитать на каком кол-ве компьютеров может произойти снижение производительности и ограничить кол-во Job

    Ограничить кол-во Job выполняющихся параллельно:

    while (@(Get-Job -State Running).Count -ge 6) {
        Start-Sleep -sec 2
    }

    • Помечено в качестве ответа Legioner 12 марта 2015 г. 14:30
    12 марта 2015 г. 11:18
    Отвечающий

Все ответы

  •  Нормальное поведение для Job, т.к. узкое место жесткий диск и сетевая подсистема. Сделать замер счетчиков производительности при последовательном и параллельном копировании, чтобы развеять сомнения. Скрипт выполняется на $Server? - Чтобы исключить лишнего промежуточного копирования.

    12 марта 2015 г. 9:48
    Отвечающий
  • Почему нормальное? Тестово проверял на одной папке с профилем - скрипт с использованием Job быстрее в 5 раз. Но если запустить Job в цикл, где 200 папок, то Job странно затягивает весь процесс.

    Да, скрипт выполняется на $Server.

    Замеры уже проводил:

    На рабочем скрипте без Job, просто последовательное выполнение - в среднем 4 часа

    С Job - два раза по 10 часов и плюс не оконченное выполнение, т.к. продолжалась работа...

    12 марта 2015 г. 10:30
  • Почему нормальное?  - Robocopy утилизирует все доступную полосу пропускания, тут создается несколько потоков, которые ведут борьбу за эту полосу и чем их больше, тем больше время на обслуживания пустых и ненужных операций.

    Если производительность жестких дисков и сетевой подсистемы сервера позволяет, то следует исправить код:

    1) Объединить все каталоги для 1 компьютера в один Job

    $scr = { 
    	param($catalog,$c,$Server = "server.contoso.com") 
        
    	foreach($uwhois in $Catalog) 
    	{ 
    		$s = '\\{0}\C$\Documents and Settings\{1}' -f $Server,$uwhois 
    		$d = '\\{0}\C$\Documents and Settings\{1}' -f $c,$uwhois 
    		
    		if (!(Test-Path $d)) 
    		{ 
    			New-Item -Path $d -type directory -Force 
    		}  
    		robocopy $s $d 
    	}
    
     } 
    
     
    foreach($c in $Computers) 
    { 
    	Start-Job -Name $c -ScriptBlock $scr -ArgumentList $Catalog,$c
    } 

    2) Посчитать на каком кол-ве компьютеров может произойти снижение производительности и ограничить кол-во Job

    Ограничить кол-во Job выполняющихся параллельно:

    while (@(Get-Job -State Running).Count -ge 6) {
        Start-Sleep -sec 2
    }

    • Помечено в качестве ответа Legioner 12 марта 2015 г. 14:30
    12 марта 2015 г. 11:18
    Отвечающий
  • я в свое время эксперементировал с копированием (необходимо было мигрировать файловый сервер с минимальным даунтаймом) и в моем конкретном случае было емнип 7 параллельных задач робокопи с выключенной с многопоточностью(/mt:1)
    12 марта 2015 г. 11:41

  • Т.е. в $Catalog находится 200 папок с профилями, а в $Servers - 5 компьютеров, получается в моем цикле было 200 итераций в цикле с 5-тью одновременными потоками robocopy, а в вашем примере наоборот - 5 итераций, по 200 копирований, с постепенным урезанием кол-ва потоков, что можно экспериментально наверное только проверить.

    Вариант интересный, спасибо попробую и так, только куда while закинуть, в строку сразу после Start-Job сразу?

    Изначально сомневался в корректности этих строк:

    get-job | wait-job   

    а подход с @(Get-Job -State Running).Count более нравится, т.к. понятнее 

    12 марта 2015 г. 11:55
  • В моем случае кол-во Job =  $Computers ( в изначальном Job =  $Catalog * $Computers) . Код с while использовать в блоке foreach($c in $Computers) .
    12 марта 2015 г. 12:03
    Отвечающий
  • Спасибо, за ваш вариант. Непременно проверю вечером, должно решить вопрос скорости.
    12 марта 2015 г. 12:58