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


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입니다.

그 의미

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


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