파일 내용을 읽는 것보다 도트 소싱 속도가 느립니까?


13

다른 소스 파일 (즉, 함수 당 하나의 .ps1 파일)에서 함수 정의를 가져 오는 PowerShell 모듈을 작성했습니다. 이를 통해 (팀으로서) 다른 기능을 동시에 수행 할 수 있습니다. 모듈 (.psm1 파일)은 사용 가능한 .ps1 파일 목록을 가져옵니다.

$Functions = Get-ChildItem -Path $FunctionPath *.ps1

그런 다음 목록을 반복하고 도트 소싱을 통해 각 함수 정의를 가져옵니다.

foreach($Function in $Functions) {
  . $Function.Fullname                                     # Can be slow
}

문제 : 테스트를 수행하는 컴퓨터에 따라이 작업이 완료되는 속도가 약 50 개의 소스 파일에 대해 10 초에서 180 초까지 크게 달라질 수 있습니다. 우리는 소요 시간의 광범위한 변화를 설명 할 수 없으며 머신 유형, OS, 사용자 계정, 관리자 권한, PS 프로파일, PS 버전 등과 같은 변수를 제어했다고 생각합니다. 동일한 호스트에서 동일한 시간 동안 동일한 시간이 소요될 수 있습니다 하루에서 다음 날까지

이것이 디스크 액세스에 문제가 있는지 궁금해하고 디스크에서 얼마나 빨리 읽을 수 있는지 테스트했습니다. Get-Content모든 파일에서 실행 하는 것이 매우 빠르다는 것을 알았습니다.이 문제에 대한 해결 방법에서 이점을 얻었습니다.

foreach($Function in $Functions) {
  Invoke-Expression (Get-Content $Function.Fullname -Raw)  # Is quick
}

파일 내용을 읽고 실행하는 것보다 점 소싱을 통해 이러한 기능을 추가하는 이유는 무엇입니까?

답변:


17

과학 설정

먼저, 이것을 테스트하는 데 도움이되는 스크립트가 있습니다. 이렇게하면 각각 하나의 작은 기능을 가진 2000 개의 스크립트 파일이 생성됩니다.

1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }

정상적인 시작 오버 헤드를 그리 중요하게 만들 수는 없습니다. 원한다면 더 추가 할 수 있습니다. 그러면 점 소싱을 사용하여 모두로드됩니다.

dir test*.ps1 | % {. $_.FullName}

먼저 내용을 먼저 읽어서 모두로드합니다.

dir test*.ps1 | % {iex (gc $_.FullName -Raw)}

이제 PowerShell의 작동 방식을 심각하게 검사해야합니다. 디 컴파일러로 JetBrains dotPeek 을 좋아 합니다. .NET 응용 프로그램에 PowerShell 을 포함 하려고 시도한 경우 대부분의 관련 항목이 포함 된 어셈블리는 System.Management.Automation. 프로젝트와 PDB로 디 컴파일하십시오.

이 모든 신비한 시간이 어디에서 소비되는지 확인하기 위해 프로파일 러를 사용합니다. Visual Studio에 내장 된 것을 좋아합니다. 사용하기 매우 쉽습니다 . PDB를 포함하는 폴더를 심볼 위치에 추가합니다 . 이제 테스트 스크립트 중 하나만 실행하는 PowerShell 인스턴스의 프로파일 링 실행을 수행 할 수 있습니다. ( -File첫 번째 스크립트의 전체 경로와 함께 사용할 명령 줄 매개 변수를 설정하십시오. 시작 위치를 모든 작은 스크립트가 포함 된 폴더로 설정하십시오.) 일단 완료되면 powershell.exe대상 아래 의 항목에서 특성을 열고 변경하십시오. 다른 스크립트를 사용하기위한 인수 그런 다음 Performance Explorer에서 최상위 항목을 마우스 오른쪽 단추로 클릭하고 프로파일 링 시작을 선택 하십시오.. 프로파일 러는 다른 스크립트를 사용하여 다시 실행됩니다. 이제 비교할 수 있습니다. 옵션이 제공되면 "모든 코드 표시"를 클릭하십시오. 저에게는 샘플 프로파일 링 보고서의 요약보기에있는 알림 영역에 표시됩니다.

결과는

내 컴퓨터에서 Get-Content버전은 2000 스크립트 파일을 통과하는 데 9 초가 걸렸습니다. "Hot Path"의 중요한 기능은 다음과 같습니다.

Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord

이것은 많은 이해 : 우리는 기다릴 필요가 Get-Content디스크에서 콘텐츠를 읽는, 우리는 기다릴 필요가 Invoke-Expression그 내용의 메이크업의 용도에 관한 것이다.

도트 소스 버전에서 내 컴퓨터는 해당 파일을 처리하는 데 15 초가 조금 걸렸습니다. 이번에는 Hot Path의 기능이 기본 메소드였습니다.

WinVerifyTrust
CodeAuthzFullyQualifyFilename

두 번째 문서는 문서화되지 않은 것으로 보이지만 WinVerifyTrust"지정된 개체에 대한 트러스트 확인 작업을 수행합니다." 그것은 당신이 얻을 수있는 한 모호하지만 다른 말로하면, 그 기능은 주어진 공급자를 사용하여 주어진 자원의 신뢰성을 확인합니다. PowerShell에 멋진 보안 기능을 활성화하지 않았으며 스크립트 실행 정책은 Unrestricted입니다.

그 의미

요컨대, 실행이 허용되는 스크립트를 제한하지 않을 때 필요하지 않더라도 각 파일이 어떤 방식으로 확인되기를 기다리고 있습니다. 서명이 있는지 확인하십시오. 사용자 gc와 iex컨텐츠가 콘솔에 기능을 입력 한 것과 같으므로 확인할 자원이 없습니다.


2
벤,이 훌륭한 답변에 감사드립니다. 디 컴파일까지 갔다는 사실에 감명 받았습니다. 이것은 제가 시도한 것 이상의 단계입니다. 이 문제가 가장 심각한 기계 중 하나에서 테스트 방법을 따를 수있는 방법이 있는지 살펴 보겠습니다. 시간이 오래 걸리므로 숨을 참지 마십시오!
— Charlie Joynt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.