Preparando la ciencia
Primero, algunos scripts para ayudarnos a probar esto. Esto genera 2000 archivos de script, cada uno con una única función pequeña:
1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }
Eso debería ser suficiente para que la sobrecarga de inicio normal no importe demasiado. Puedes agregar más si quieres. Esto los carga a todos usando el abastecimiento de puntos:
dir test*.ps1 | % {. $_.FullName}
Esto los carga a todos leyendo primero su contenido:
dir test*.ps1 | % {iex (gc $_.FullName -Raw)}
Ahora necesitamos hacer una inspección seria de cómo funciona PowerShell. Me gusta JetBrains dotPeek para un descompilador. Si alguna vez ha intentado incrustar PowerShell en una aplicación .NET , encontrará que el ensamblado que incluye la mayoría de las cosas relevantes es System.Management.Automation
. Descompilarlo en un proyecto y un PDB.
Para ver dónde se está gastando todo este tiempo misterioso, utilizaremos un generador de perfiles. Me gusta el que está integrado en Visual Studio. Es muy fácil de usar . Agregue la carpeta que contiene el PDB a las ubicaciones de los símbolos . Ahora, podemos hacer una ejecución de creación de perfiles de una instancia de PowerShell que solo ejecuta uno de los scripts de prueba. (Establezca los parámetros de la línea de comandos para usar -File
con la ruta completa de la primera secuencia de comandos que intente. Establezca la ubicación de inicio en la carpeta que contiene todas las secuencias de comandos pequeñas.) Una vez que haya terminado, abra las Propiedades en la powershell.exe
entrada en Objetivos y cambie Los argumentos para utilizar el otro script. A continuación, haga clic con el botón derecho en el elemento superior en el Explorador de rendimiento y seleccione Iniciar creación de perfiles. El generador de perfiles se ejecuta nuevamente utilizando el otro script. Ahora podemos comparar. Asegúrese de hacer clic en "Mostrar todo el código" si se le da la opción; para mí, eso aparece en un área de Notificaciones en la vista Resumen del Informe de perfil de muestra.
Los resultados llegan
En mi máquina, la Get-Content
versión tardó 9 segundos en revisar los archivos de script 2000. Las funciones importantes en el "Hot Path" fueron:
Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord
Esto tiene mucho sentido: tenemos que esperar para Get-Content
leer el contenido del disco, y tenemos que esperar para Invoke-Expression
hacer uso de esos contenidos.
En la versión de fuente de puntos, mi máquina pasó un poco más de 15 segundos para trabajar con esos archivos. Esta vez, las funciones en el Hot Path eran métodos nativos:
WinVerifyTrust
CodeAuthzFullyQualifyFilename
El segundo no parece estar documentado, pero WinVerifyTrust
"realiza una acción de verificación de confianza en un objeto específico". Eso es lo más vago que puede ser, pero en otras palabras, esa función verifica la autenticidad de un recurso dado usando un proveedor dado. Tenga en cuenta que no he habilitado ningún elemento de seguridad sofisticado para PowerShell, y mi política de ejecución de script es Unrestricted
.
Lo que eso significa
En resumen, está esperando que cada archivo se verifique de alguna manera, probablemente se verificó una firma, aunque eso no es necesario cuando no restringe los scripts que se pueden ejecutar. Cuando usted gc
y luego iex
los contenidos, es como si hubiera escrito las funciones en la consola, por lo que no hay recursos para verificar.