Нужна помощь в повышении производительности сценария синтаксического анализа PowerShell с разделителями - PullRequest
6 голосов
/ 18 января 2012

Мне нужно проанализировать большой файл с разделителями каналов, чтобы подсчитать количество записей, чей 5-й столбец соответствует и не соответствует моим критериям.

PS C:\temp> gc .\items.txt -readcount 1000 | `
  ? { $_ -notlike "HEAD" } | `
  % { foreach ($s in $_) { $s.split("|")[4] } } | `
  group -property {$_ -ge 256} -noelement | `
  ft –autosize

Эта команда делает то, что я хочу, возвращая вывод примерно так:

  Count Name
  ----- ----
1129339 True
2013703 False

Однако для тестового файла объемом 500 МБ выполнение этой команды занимает около 5,5 минут, что измеряется с помощью Measure-Command. Типичный файл занимает более 2 ГБ, где ожидание более 20 минут нежелательно долго.

Видите ли вы способ улучшить производительность этой команды?

Например, есть ли способ определить оптимальное значение для ReadCount Get-Content? Без этого требуется 8,8 минуты, чтобы завершить тот же файл.

Ответы [ 3 ]

4 голосов
/ 18 января 2012

Используя подсказку @ Gisli, вот скрипт, с которым я закончил:

param($file = $(Read-Host -prompt "File"))
$fullName = (Get-Item "$file").FullName
$sr = New-Object System.IO.StreamReader("$fullName")
$trueCount = 0; 
$falseCount = 0; 
while (($line = $sr.ReadLine()) -ne $null) {
      if ($line -like 'HEAD|') { continue }
      if ($line.split("|")[4] -ge 256) { 
            $trueCount++
      }
      else {
            $falseCount++
      }
}
$sr.Dispose() 
write "True count:   $trueCount"
write "False count: $falseCount"

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

4 голосов
/ 18 января 2012

Вы пробовали StreamReader? Я думаю, что Get-Content загружает весь файл в память, прежде чем что-то с ним делать.

Класс StreamReader

2 голосов
/ 18 января 2012

Просто добавьте еще один пример с использованием StreamReader для чтения очень большого файла журнала IIS и вывода всех уникальных IP-адресов клиентов и некоторых показателей производительности.

$path = 'A_245MB_IIS_Log_File.txt'
$r = [IO.File]::OpenText($path)

$clients = @{}

while ($r.Peek() -ge 0) {
    $line = $r.ReadLine()

    # String processing here...
    if (-not $line.StartsWith('#')) {
        $split = $line.Split()
        $client = $split[-5]
        if (-not $clients.ContainsKey($client)){
            $clients.Add($client, $null)
        }
    }
}

$r.Dispose()
$clients.Keys | Sort

Небольшое сравнение производительности с Get-Content:

StreamReader : Завершено: 5,5 секунд, PowerShell.exe: 35,328 КБ ОЗУ.

Get-Content : Завершено: 23,6 секунды. PowerShell.exe: 1 110 524 КБ ОЗУ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...