2017-01-20 11 views
0

Я работаю над скриптом PowerShell для преобразования журнала ping в данные диаграммы.Операция медленного массива в Powershell

Скрипт работает нормально, но работает очень медленно, вызванный операциями массива.

Если сценарий, выполняемый в файле строки 10k, занимает около 7 секунд. Если операция массива удалена, то для завершения требуется меньше секунды.

Я ищу альтернативное решение для возврата данных к функции вызывающего абонента без использования временного массива.

Пример логе ввода:

02.01.2017-14:53:54> Reply from 8.8.8.8: bytes=32 time=184ms TTL=57 
02.01.2017-14:53:54> Reply from 8.8.8.8: bytes=32 time=18ms TTL=57 
02.01.2017-14:53:59> Request timed out. 
02.01.2017-14:54:01> Reply from 192.168.2.186: Destination host unreachable. 
02.01.2017-14:54:05> Request timed out. 
02.01.2017-14:54:07> Reply from 192.168.2.186: Destination host unreachable. 

Сценарий:

function Convert-V4PingLog2ChartData 
{ 
    param($V4PingLogFile, $AvarageRespondTime, $ChartCounter) 
    $ConvertedData="" 
    $var=Get-Content $V4PingLogFile 
    $varArray=$var.split("`n") 
    $varArray=$varArray | Select-Object -Skip 2 

    $CommandExecuteTime=Measure-Command{ 

    $pattern = "^([0-9]{2})\.([0-9]{2})\.([0-9]{4})-([0-9]{2}):([0-9]{2}):([0-9]{2})> Reply from [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}: bytes=32 time=([0-9]{1,4})ms TTL=[0-9]{1,3}$"; 
    $pattern2="^([0-9]{2})\.([0-9]{2})\.([0-9]{4})-([0-9]{2}):([0-9]{2}):([0-9]{2})> (Request timed out.|Reply from [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}: Destination host unreachable.)$" 

    foreach($nextLine in $varArray) 
    { 
     if($nextLine -like "* time=*")  
     { 
      $ConvertedData+=$nextLine -replace $pattern, "data$ChartCounter.addRow([new Date(`$3, `$2, `$1, `$4, `$5, `$6, 00), `$7, $AvarageRespondTime]);" 
     } 
     else 
     { 
      $ConvertedData+=$nextLine -replace $pattern2, "data$ChartCounter.addRow([new Date(`$3, `$2, `$1, `$4, `$5, `$6, 00), 0, $AvarageRespondTime]);" 
     } 
    } 
    } 
    Write-Host $CommandExecuteTime 
    return $ConvertedData 
} 

ответ

1

На самом деле, вы добавления в строку, а не массив, но это обязательно будет медленным, а также.

Изменить это:

$ConvertedData="" 
... 
foreach($nextLine in $varArray) 
{ 
    if($nextLine -like "* time=*")  
    { 
     $ConvertedData+=$nextLine -replace ... 
    } 
    else 
    { 
     $ConvertedData+=$nextLine -replace ... 
    } 
} 

в этом:

$ConvertedData = foreach ($nextLine in $varArray) { 
    if ($nextLine -like "* time=*") { 
     $nextLine -replace ... 
    } else { 
     $nextLine -replace ... 
    } 
} 
$ConvertedData -join "`n" 

, чтобы ускорить процесс.

+0

Спасибо, он отлично работает – Krisz

+0

Thats a nice ansgar :) –

0

привет попробовать что-то вроде этого:

[email protected]" 
{Timelog*:02.01.2017-14:53:54}> {TypeRow:Reply} {Detail:from {IP:8.8.8.8}: {Detailbytes:bytes=32} {Detailtime:time=184ms} {DetailTTL:TTL=57}} 
{Timelog*:15.15.2018-20:30:00}> {TypeRow:Reply} {Detail:from {IP:18.28.38.48}: {Detailbytes:bytes=32} {Detailtime:time=184ms} {DetailTTL:TTL=57}} 
{Timelog*:02.01.2017-14:53:54}> {TypeRow:Reply} {Detail:from {IP:1.2.345.678}: {Detailbytes:bytes=32} {Detailtime:time=184ms} {DetailTTL:TTL=57}} 
{Timelog*:04.01.2017-14:53:59}> {TypeRow:Request} {Detail:{Message:timed out.}} 
{Timelog*:03.01.2017-14:54:01}> {TypeRow:Reply} {Detail:from {IP:192.168.2.186}: {Message:Destination host unreachable.}} 
{Timelog*:12.01.2017-14:54:05}> {TypeRow:Request} {Detail:{Message:timed out.}} 
{Timelog*:02.01.2017-14:54:07}> {TypeRow:Reply} {Detail:from {IP:255.255.255.255}: {Message:Destination host unreachable.}} 
"@ 

get-Content C:\temp\File.txt | ConvertFrom-String -TemplateContent $template | 
%{ 
    [pscustomobject]@{ 
    Timelog=$_.Timelog 
    TypeRow=$_.TypeRow 
    IP=$_.Message.IP 
    Detailbytes=if ($_.Detail.Message -ne $null) {''} else {$_.Detail.Detailbytes} 
    Detailtime=if ($_.Detail.Message -ne $null) {''} else {$_.Detail.Detailtime} 
    DetailTTL=if ($_.Detail.Message -ne $null) {''} else {$_.Detail.DetailTTL} 
    Error=$_.Detail.Message 
    } 
} | Format-Table 
+0

Спасибо, приятное решение и совсем другое приближающееся :), я пробовал в журнале 100K и всего 23 секунды. – Krisz

0

Во-первых, как писал Ansgar, вы добавляете в строку, а не массив. Но проблема в обоих случаях одинакова. В .NET оба массива и строки неизменяемы (размеры массива, а не контент). Каждый раз, когда вы добавляете что-то в массив или строку, система копирует старый контент в новую ячейку памяти, а затем добавляет новые данные.

В массивах вы можете преодолеть эту проблему, если вручную изменить размер массива до конечного размера, который вы ожидаете. Размер resize копирует массив, , но он делает это один раз, а не при каждом добавлении. Разница в скорости может быть HUGE!

Давайте рассмотрим следующую команду, которая присоединяет 10000 элементов в пустой массив:

$a = @(); Measure-Command { for($i = 0; $i -lt 10000; $i++) { $a += $i } } 

Выполнение этой команды я получил следующие результаты

Days    : 0 
Hours    : 0 
Minutes   : 0 
Seconds   : 3 
Milliseconds  : 534 
Ticks    : 35342407 
TotalDays   : 4,09055636574074E-05 
TotalHours  : 0,000981733527777778 
TotalMinutes  : 0,0589040116666667 
TotalSeconds  : 3,5342407 
TotalMilliseconds : 3534,2407 

Теперь рассмотрим следующую команду. Сначала он изменяет размер массива, используя статическую функцию Resize объекта Array, а затем устанавливает 10000 с помощью индексации.

$b = @(); Measure-Command { 
    [array]::Resize([ref]$b,10000); 
    for($i = 0; $i -lt 10000; $i++) { $b[$i] = $i } 
} 

Результаты:

Days    : 0 
Hours    : 0 
Minutes   : 0 
Seconds   : 0 
Milliseconds  : 40 
Ticks    : 402365 
TotalDays   : 4,65700231481481E-07 
TotalHours  : 1,11768055555556E-05 
TotalMinutes  : 0,000670608333333333 
TotalSeconds  : 0,0402365 
TotalMilliseconds : 40,2365 

Прогон падение время от 3,5 секунды до всего 40 миллисекунд!

Вы можете комбинировать эту технику с техникой Ансгара. Измените размер массива, добавьте результаты в измененный массив и в конце присоедините массив к огромной строке.

Некоторые замечания. Вы можете вызывать изменение размера столько раз, сколько хотите, давая новый размер массива каждый раз. Вы можете получить текущий размер массива, используя свойство Length массива. Если вы достигли предела и вам нужно больше места, просто позвоните по размеру и добавьте еще один большой кусок.

Я не уверен, что вы увидите много улучшений, но если вы действительно очень хотите идти как можно быстрее, вы должны пойти в MSDN и взглянуть на класс Добавить в словарь. Это рекомендуемый класс для подобных идей, но использовать PowerShell не так просто.

 Смежные вопросы

  • Нет связанных вопросов^_^