2014-04-20 2 views
1

나는 이진 파일 나는 진 구문 분석의 세부 사항에 가고 싶지 않아PowerShell을 - 이진 파일 성능이 저하

Param(
    [Parameter(Mandatory=$True)] 
    [string]$inputFilePath 
) 

function GetLengthFrom2Byte 
{ 
    Param(
     [Parameter(Mandatory=$True)] 
     [byte[]]$bytes 
    ) 

    if ($bytes.Length -ne 2) 
    { 
     echo "Parametro di Input non valido"  
    } 
    else 
    { 
     $lenByte = New-Object Byte[](2) 

     $lenByte[0] = $bytes[1] 
     $lenByte[1] = $bytes[0] 

     return [BitConverter]::ToUInt16($lenByte, 0) 
    } 
} 

try 
{ 
    if (!(Test-Path($inputFilePath))) 
    { 
     Throw "File di Input non valido: <{0}>" -f $inputFilePath  
    } 

    $inputStream = New-Object IO.FileStream($inputFilePath, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read) 
    $inputBinaryReader = New-Object IO.BinaryReader($inputStream) 

    while ($inputBinaryReader.PeekChar() -ne -1) 
    { 
     $AfpHeader = $inputBinaryReader.ReadByte() 

     if ($AfpHeader -ne 0x5A) 
     { 
      Throw "Errore nella struttura AFP. Byte 0x5A non trovato all' offset: <{0}>" -f $inputBinaryReader.BaseStream.Position 
      exit 8 
     } 

     $AfpLength = $inputBinaryReader.ReadBytes(2) 

     $recordLength = GetLengthFrom2Byte($AfpLength) 

     $inputBinaryReader.ReadBytes($recordLength - 2) > $null 
    } 

    echo "File AFP Validato" 
} 
catch [Exception] 
{ 
    echo "Errore: {0}" -f $error[0] 
    exit 8 
} 
finally 
{ 
    $inputBinaryReader.Dispose() 
    $inputStream.Dispose() 
} 

exit 0 

을 구문 분석 다음 코드를 작성했습니다. 문제는 PowerShell에서 11 분이 걸린 반면 C#의 동일한 기능은 약 50 초가 걸렸습니다.

동일한 클래스를 사용하고 있기 때문에 왜 그 차이가 너무 큰지 알 수 없습니다. PowerShell 성능을 향상시킬 방법이 있습니까?

$lenByte = New-Object Byte[](2) 

를 그래서 그냥 한 번 발생하는 것이 : 당신이 스크립트 범위에이 라인을 이동하는 경우

+0

정확히 무엇이 문제입니까? –

+2

PowerShell이 ​​해석되는 동안 C#이 컴파일된다는 것을 알고 있습니까? –

+0

@EugenRieck 네, 저도 압니다 만, 그 차이가 너무 크지는 않습니까? –

답변

2

당신은 가장 큰 성능 향상을 얻을 것이다. 그런 다음 참조를 '$ script : lenByte'로 변경해야합니다.

로컬 함수 GetLengthFrom2Byte 만들기를 건너 뛰고 대신 해당 스크립트의 비트를 인라인하면 성능이 향상됩니다.

2 가지가 변경된 후에는 성능이 C#과 더 비슷해야한다고 생각합니다.

PowerShell V3부터는 스크립트와 루프가 16 번 실행 된 후에 네이티브 코드로 컴파일되기 때문에 C#과 비슷한 성능을 얻을 수 있지만 대부분의 경우 불가능한 특정 PowerShell 기능을 피할 수 있어야합니다. 명령에 대한

  • 검색 당신이 그것을 실행할 때마다 :

    PowerShell은 cmdlet을 호출

    은 PowerShell을 당신이 그것을 실행할 때마다 다음과 같은 작업을 수행하기 때문에 새로운-Object가 상당히 비싸다 같다. New-Object의 경우 검색은 cmdlet을 찾기 전에 여러 범위의 여러 명령 유형을 검색합니다. (반사를 사용)
  • 바인딩 매개 변수
  • 가 System.Type 인스턴스
  • 에 문자열 매개 변수를 변환의 모든 것을 반사를 통해
  • 전화를

참고 생성자를 호출 할 생성자 결정 위의 사항이 훨씬 빨라질 수 있습니다. 아직 발생하지 않았습니다.

PowerShell은 로컬 함수 인 GetLengthFrom2Byte에 대해 비슷한 작업을 수행해야합니다. 명령을 검색해야하는 범위가 적어지기 때문에 약간 낫습니다. 매개 변수에는 여전히 변환이 필요하지만 2 개의 요소로 이루어진 배열을 변환하는 것은 문자열에서 유형으로의 변환보다 훨씬 빠릅니다.

순수한 .Net 스타일 코드 (내부 루프에 PowerShell 함수가 사용되지 않음)를 사용한 후에도 PowerShell의 동적 특성 때문에 성능이 여전히 C#보다 나빠질 수 있습니다. 예를 들어, 속성에 액세스하거나 .NET 메서드를 호출 할 때마다 PowerShell은 대상 개체의 형식과 메서드 인수의 형식을 확인해야합니다. V3에서 이러한 작업은 V2보다 훨씬 빠르지 만 PowerShell 언어 의미를 보장하기 위해 반드시 수행해야하는 동적 검사가 있습니다.

관련 문제