Preparare la scienza
Innanzitutto, alcuni script per aiutarci a testare questo. Questo genera 2000 file di script, ognuno con una singola piccola funzione:
1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }
Dovrebbe essere sufficiente per non importare troppo il normale sovraccarico di avvio. Puoi aggiungere altro se vuoi. Questo li carica tutti usando dot-sourcing:
dir test*.ps1 | % {. $_.FullName}
Questo li carica tutti leggendo prima il loro contenuto:
dir test*.ps1 | % {iex (gc $_.FullName -Raw)}
Ora dobbiamo fare alcune ispezioni serie su come funziona PowerShell. Mi piace JetBrains dotPeek per un decompilatore. Se hai mai provato a incorporare PowerShell in un'applicazione .NET , scoprirai che è l'assembly che include la maggior parte delle cose rilevanti System.Management.Automation
. Decompila quello in un progetto e un PDB.
Per vedere dove viene trascorso tutto questo tempo misterioso, useremo un profiler. Mi piace quello integrato in Visual Studio. È molto facile da usare . Aggiungi la cartella contenente il PDB nelle posizioni dei simboli . Ora, possiamo eseguire un'esecuzione di profilatura di un'istanza di PowerShell che esegue solo uno degli script di test. (Impostare i parametri della riga di comando da utilizzare -File
con il percorso completo del primo script da provare. Impostare la posizione di avvio sulla cartella contenente tutti gli script minuscoli.) Una volta fatto quello, aprire le Proprietà sulla powershell.exe
voce in Target e modificare gli argomenti per usare l'altro script. Quindi fare clic con il pulsante destro del mouse sull'elemento più in alto in Performance Explorer e selezionare Avvia profilatura. Il profiler viene eseguito nuovamente utilizzando l'altro script. Ora possiamo confrontare. Assicurati di fare clic su "Mostra tutto il codice" se ti viene data l'opzione; per me, che appare in un'area Notifiche nella vista Riepilogo del Rapporto di profilazione di esempio.
I risultati arrivano
Sul mio computer, la Get-Content
versione ha impiegato 9 secondi per passare attraverso i file di script 2000. Le funzioni importanti sul "Hot Path" erano:
Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord
Questo ha molto senso: dobbiamo aspettare per Get-Content
leggere il contenuto dal disco e dobbiamo aspettare per Invoke-Expression
fare uso di tali contenuti.
Nella versione dot-source, la mia macchina impiegava poco più di 15 secondi a lavorare su quei file. Questa volta, le funzioni su Hot Path erano metodi nativi:
WinVerifyTrust
CodeAuthzFullyQualifyFilename
Il secondo sembra non essere documentato, ma WinVerifyTrust
"esegue un'azione di verifica della fiducia su un oggetto specificato". È più vago che puoi ottenere, ma in altre parole, quella funzione verifica l'autenticità di una determinata risorsa utilizzando un determinato provider. Si noti che non ho abilitato alcuna roba di sicurezza sofisticata per PowerShell e la mia politica di esecuzione degli script è Unrestricted
.
Cosa significa
In breve, stai aspettando che ogni file venga verificato in qualche modo, probabilmente controllato per una firma, anche se questo non è necessario quando non limiti gli script che possono essere eseguiti. Quando tu gc
e poi iex
i contenuti, è come se avessi digitato le funzioni sulla console, quindi non c'è risorsa da verificare.