Tworzenie nauki
Po pierwsze, kilka skryptów, które pomogą nam to przetestować. Generuje to 2000 plików skryptów, każdy z jedną małą funkcją:
1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }
To powinno wystarczyć, aby normalny koszt początkowy nie miał zbytniego znaczenia. Możesz dodać więcej, jeśli chcesz. Spowoduje to załadowanie ich wszystkich za pomocą pozyskiwania kropek:
dir test*.ps1 | % {. $_.FullName}
Spowoduje to załadowanie ich wszystkich, najpierw czytając ich zawartość:
dir test*.ps1 | % {iex (gc $_.FullName -Raw)}
Teraz musimy dokonać poważnej inspekcji działania programu PowerShell. Lubię JetBrains dotPeek dla dekompilatora. Jeśli kiedykolwiek próbowałeś osadzić PowerShell w aplikacji .NET , przekonasz się, że jest to zestaw zawierający większość istotnych elementów System.Management.Automation
. Zdekompiluj to do projektu i PDB.
Aby zobaczyć, gdzie spędza się cały ten tajemniczy czas, użyjemy profilera. Podoba mi się ten wbudowany w Visual Studio. Jest bardzo łatwy w użyciu . Dodaj folder zawierający PDB do lokalizacji symboli . Teraz możemy przeprowadzić profilowanie instancji PowerShell, która po prostu uruchamia jeden ze skryptów testowych. (Ustaw parametry wiersza polecenia do użycia -File
z pełną ścieżką pierwszego skryptu do wypróbowania. Ustaw lokalizację uruchamiania do folderu zawierającego wszystkie małe skrypty.) Po zakończeniu, otwórz Właściwości w powershell.exe
pozycji pod Celami i zmień argumenty, aby użyć drugiego skryptu. Następnie kliknij prawym przyciskiem myszy najwyższy element w Eksploratorze wydajności i wybierz opcję Rozpocznij profilowanie. Program profilujący uruchamia się ponownie przy użyciu drugiego skryptu. Teraz możemy porównać. Upewnij się, że kliknąłeś „Pokaż cały kod”, jeśli podano opcję; dla mnie to pokazuje się w obszarze powiadomień w widoku Podsumowanie przykładowego raportu profilowania.
Wyniki wchodzą
Na moim komputerze Get-Content
wersja zajęła 9 sekund przejście przez pliki skryptów 2000. Ważnymi funkcjami „Hot Path” były:
Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord
Ma to sens: musimy poczekać na Get-Content
odczyt zawartości z dysku i musimy poczekać, aż Invoke-Expression
z niej skorzystamy.
W wersji źródłowej moja maszyna poświęciła nieco ponad 15 sekund na przeglądanie tych plików. Tym razem funkcje na Hot Path były metodami natywnymi:
WinVerifyTrust
CodeAuthzFullyQualifyFilename
Drugi wydaje się być nieudokumentowany, ale WinVerifyTrust
„wykonuje akcję weryfikacji zaufania do określonego obiektu”. To jest tak niejasne, jak to tylko możliwe, ale innymi słowy, funkcja ta weryfikuje autentyczność danego zasobu za pomocą danego dostawcy. Zauważ, że nie włączyłem żadnych wymyślnych zabezpieczeń dla PowerShell, a moje zasady wykonywania skryptów są Unrestricted
.
Co to znaczy
Krótko mówiąc, czekasz na jakąś weryfikację każdego pliku, prawdopodobnie sprawdzoną pod kątem podpisu, nawet jeśli nie jest to konieczne, gdy nie ograniczysz skryptów, które mogą być uruchamiane. Kiedy ty, gc
a potem iex
zawartość, to tak, jakbyś wpisał funkcje w konsoli, więc nie ma zasobów do zweryfikowania.