Mise en place de la science
Premièrement, quelques scripts pour nous aider à tester cela. Cela génère 2000 fichiers de script, chacun avec une seule petite fonction:
1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }
Cela devrait suffire à faire en sorte que les frais généraux de démarrage ne importent pas trop. Vous pouvez en ajouter plus si vous le souhaitez. Cela les charge tous en utilisant la source de points:
dir test*.ps1 | % {. $_.FullName}
Cela les charge tous en lisant d'abord leur contenu:
dir test*.ps1 | % {iex (gc $_.FullName -Raw)}
Nous devons maintenant examiner sérieusement le fonctionnement de PowerShell. J'aime JetBrains dotPeek pour un décompilateur. Si vous avez déjà essayé d' intégrer PowerShell dans une application .NET , vous constaterez que l'assemblage qui contient la plupart des éléments pertinents est System.Management.Automation
. Décompiler celui-ci dans un projet et un PDB.
Pour voir où tout ce temps mystérieux est passé, nous allons utiliser un profileur. J'aime celui intégré à Visual Studio. C'est très facile à utiliser . Ajoutez le dossier contenant le PDB aux emplacements des symboles . Maintenant, nous pouvons effectuer une exécution de profilage d’une instance PowerShell qui n’exécute que l’un des scripts de test. (Définissez les paramètres de ligne de commande à utiliser -File
avec le chemin d'accès complet du premier script à essayer. Définissez l'emplacement de démarrage sur le dossier contenant tous les scripts minuscules.) Une fois celui-ci terminé, ouvrez les propriétés de l' powershell.exe
entrée sous Cibles et modifiez-le. les arguments pour utiliser l'autre script. Cliquez ensuite avec le bouton droit sur l'élément le plus en haut dans Performance Explorer et choisissez Démarrer le profilage.. Le profileur s'exécute à nouveau à l'aide de l'autre script. Maintenant nous pouvons comparer. Assurez-vous de cliquer sur "Afficher tout le code" si l'option vous est proposée. pour moi, cela apparaît dans une zone de notifications dans la vue Résumé du rapport de profilage d'échantillonnage.
Les résultats arrivent
Sur ma machine, il Get-Content
a fallu 9 secondes à la version pour parcourir les 2 000 fichiers de script. Les fonctions importantes sur le "Hot Path" étaient:
Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord
Cela a beaucoup de sens: nous devons attendre Get-Content
de lire le contenu du disque, et Invoke-Expression
d’utiliser ce contenu.
Sur la version à source ponctuelle, ma machine a mis un peu plus de 15 secondes à parcourir ces fichiers. Cette fois, les fonctions du Hot Path étaient des méthodes natives:
WinVerifyTrust
CodeAuthzFullyQualifyFilename
Le second semble non documenté, mais WinVerifyTrust
"effectue une action de vérification de confiance sur un objet spécifié". C'est à peu près aussi vague que possible, mais en d'autres termes, cette fonction vérifie l'authenticité d'une ressource donnée à l'aide d'un fournisseur donné. Notez que je n'ai activé aucun élément de sécurité sophistiqué pour PowerShell et que ma stratégie d'exécution de script est Unrestricted
.
Ce que cela signifie
En bref, vous attendez que chaque fichier soit vérifié d’une manière ou d’une autre, probablement à la recherche d’une signature, même si cela n’est pas nécessaire si vous ne limitez pas le nombre de scripts autorisés à être exécutés. Quand vous gc
et ensuite iex
le contenu, c'est comme si vous aviez tapé les fonctions sur la console, il n'y a donc aucune ressource à vérifier.