Digamos que tiene un método o un cmdlet que devuelve algo, pero no desea usarlo y no desea generarlo. Encontré estas dos formas:
Add-Item > $null
[void]Add-Item
Add-Item | Out-Null
¿Que usas? ¿Cuál es el enfoque mejor / más limpio? ¿Por qué?
Digamos que tiene un método o un cmdlet que devuelve algo, pero no desea usarlo y no desea generarlo. Encontré estas dos formas:
Add-Item > $null
[void]Add-Item
Add-Item | Out-Null
¿Que usas? ¿Cuál es el enfoque mejor / más limpio? ¿Por qué?
Respuestas:
Acabo de hacer algunas pruebas de las cuatro opciones que conozco.
Measure-Command {$(1..1000) | Out-Null}
TotalMilliseconds : 76.211
Measure-Command {[Void]$(1..1000)}
TotalMilliseconds : 0.217
Measure-Command {$(1..1000) > $null}
TotalMilliseconds : 0.2478
Measure-Command {$null = $(1..1000)}
TotalMilliseconds : 0.2122
## Control, times vary from 0.21 to 0.24
Measure-Command {$(1..1000)}
TotalMilliseconds : 0.2141
Por lo tanto, sugeriría que use cualquier cosa menos Out-Null
por sobrecarga. La siguiente cosa importante, para mí, sería la legibilidad. Me gusta redirigirme $null
y establecerme igual a $null
mí mismo. Solía preferir enviar contenido [Void]
, pero eso puede no ser tan comprensible cuando se mira el código o para nuevos usuarios.
Supongo que prefiero ligeramente redirigir la salida a $null
.
Do-Something > $null
Editar
Después del comentario de stej nuevamente, decidí hacer algunas pruebas más con tuberías para aislar mejor la sobrecarga de destruir la salida.
Aquí hay algunas pruebas con una simple tubería de 1000 objetos.
## Control Pipeline
Measure-Command {$(1..1000) | ?{$_ -is [int]}}
TotalMilliseconds : 119.3823
## Out-Null
Measure-Command {$(1..1000) | ?{$_ -is [int]} | Out-Null}
TotalMilliseconds : 190.2193
## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}
TotalMilliseconds : 119.7923
En este caso, Out-Null
tiene una sobrecarga del 60% y > $null
una sobrecarga del 0.3%.
Anexo 2017-10-16: Originalmente pasé por alto otra opción con Out-Null
el uso del -inputObject
parámetro. Al usar esto, la sobrecarga parece desaparecer, sin embargo, la sintaxis es diferente:
Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})
Y ahora para algunas pruebas con una simple tubería de 100 objetos.
## Control Pipeline
Measure-Command {$(1..100) | ?{$_ -is [int]}}
TotalMilliseconds : 12.3566
## Out-Null
Measure-Command {$(1..100) | ?{$_ -is [int]} | Out-Null}
TotalMilliseconds : 19.7357
## Redirect to $null
Measure-Command {$(1..1000) | ?{$_ -is [int]} > $null}
TotalMilliseconds : 12.8527
Aquí nuevamente Out-Null
tiene aproximadamente un 60% de gastos generales. Mientras que > $null
tiene una sobrecarga de aproximadamente el 4%. Los números aquí variaron un poco de una prueba a otra (corrí cada uno unas 5 veces y elegí el término medio). Pero creo que muestra una razón clara para no usar Out-Null
.
Out-Null
es tal vez por encima. Pero ... si canaliza un objeto a Out-Null
0.076 milisegundos, en mi opinión, todavía está perfectamente bien para el lenguaje de scripting :)
Me doy cuenta de que este es un hilo viejo, pero para aquellos que toman la respuesta aceptada de @ JasonMArcher como un hecho, me sorprende que no se haya corregido, muchos de nosotros lo hemos sabido durante años, en realidad es la TUBERÍA agregando el retraso y NADA que ver con si es Out-Null o no. De hecho, si ejecuta las pruebas a continuación, verá rápidamente que el mismo lanzamiento "más rápido" a [void] y $ void = que durante años todos usamos pensando que era más rápido, en realidad son TAN LENTOS y de hecho MUY LENTOS cuando agrega CUALQUIER canalización de ningún tipo. En otras palabras, tan pronto como conectas algo, toda la regla de no usar out-null entra en la basura.
Prueba, las últimas 3 pruebas en la lista a continuación. El horrible Out-null fue de 32339.3792 milisegundos, pero espera: ¿cuánto más rápido fue lanzar a [void]? 34121.9251 ms?!? WTF? Estos son números REALES en mi sistema, transmitir a VOID fue en realidad MÁS LENTO. ¿Qué tal = $ nulo? 34217.685ms ..... ¡aún más lento! Entonces, como muestran las últimas tres pruebas simples, el Out-Null es en realidad MÁS RÁPIDO en muchos casos cuando la tubería ya está en uso.
Entonces, ¿por qué es esto? Sencillo. Es y siempre fue 100% una alucinación que la tubería a Out-Null fue más lenta. Sin embargo, es que TUBERÍA A CUALQUIER COSA es más lento, ¿y no lo sabíamos ya por lógica básica? Es posible que no sepamos MUCHO más lento, pero estas pruebas cuentan una historia sobre el costo del uso de la tubería si puede evitarlo. Y, en realidad, no estábamos 100% equivocados porque hay un número muy PEQUEÑO de escenarios verdaderos donde el nulo es malo. ¿Cuando? Al agregar Out-Null se agrega la ÚNICA actividad de canalización. En otras palabras ... la razón de un comando simple como $ (1..1000) | Out-Null como se muestra arriba mostró cierto.
Si simplemente agrega una tubería adicional a Out-String en cada prueba anterior, los # cambian radicalmente (o simplemente pegan los siguientes) y, como puede ver por usted mismo, Out-Null en realidad se vuelve MÁS RÁPIDO en muchos casos:
$GetProcess = Get-Process
# Batch 1 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Out-Null
}
}).TotalMilliseconds
# Batch 1 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess)
}
}).TotalMilliseconds
# Batch 1 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess
}
}).TotalMilliseconds
# Batch 2 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Select-Object -Property ProcessName | Out-Null
}
}).TotalMilliseconds
# Batch 2 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Select-Object -Property ProcessName )
}
}).TotalMilliseconds
# Batch 2 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Select-Object -Property ProcessName
}
}).TotalMilliseconds
# Batch 3 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name | Out-Null
}
}).TotalMilliseconds
# Batch 3 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name )
}
}).TotalMilliseconds
# Batch 3 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Select-Object -Property Handles, NPM, PM, WS, VM, CPU, Id, SI, Name
}
}).TotalMilliseconds
# Batch 4 - Test 1
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$GetProcess | Out-String | Out-Null
}
}).TotalMilliseconds
# Batch 4 - Test 2
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
[void]($GetProcess | Out-String )
}
}).TotalMilliseconds
# Batch 4 - Test 3
(Measure-Command {
for ($i = 1; $i -lt 99; $i++)
{
$null = $GetProcess | Out-String
}
}).TotalMilliseconds
Out-Null
una tubería en absoluto, por lo que la mejor manera de mostrar la sobrecarga de una tubería es invocar Out-Null
con y sin ella. En mi sistema, por 10,000 iteraciones obtengo 0.576 segundos por Out-Null -InputObject $GetProcess
vs. 5.656 segundos (casi 10 veces más lento) $GetProcess | Out-Null
.
[void]
y $null
aún obtuve mejores resultados | Out-Null
. Entiendo que esto se debe a la tubería y el delta se reduce con los lotes posteriores, pero en mi máquina Out-Null
no funciona más rápido en ninguno de los lotes.
[void]
y $null
funcionará mejor que | Out-Null
- debido a |
. Intenta hacer Out-Null -InputObject (expression)
una comparación.
También está el Out-Null
cmdlet, que puede usar en una tubería, por ejemplo Add-Item | Out-Null
.
NAME
Out-Null
SYNOPSIS
Deletes output instead of sending it to the console.
SYNTAX
Out-Null [-inputObject <psobject>] [<CommonParameters>]
DETAILED DESCRIPTION
The Out-Null cmdlet sends output to NULL, in effect, deleting it.
RELATED LINKS
Out-Printer
Out-Host
Out-File
Out-String
Out-Default
REMARKS
For more information, type: "get-help Out-Null -detailed".
For technical information, type: "get-help Out-Null -full".
[void]
pesar de que la solución Out-Null parece más "poderosa".
[void]
ve muy claro (aunque no es tan potente como dije), verá al comienzo de la línea que no hay salida en esta línea. Entonces, esta es otra ventaja, y si haces un Out-Null en un bucle grande, el rendimiento podría ser un problema;)
Consideraría usar algo como:
function GetList
{
. {
$a = new-object Collections.ArrayList
$a.Add(5)
$a.Add('next 5')
} | Out-Null
$a
}
$x = GetList
La salida de $a.Add
no se devuelve, lo que se aplica a todas las $a.Add
llamadas a métodos. De lo contrario, deberá anteponer [void]
antes de cada llamada.
En casos simples, preferiría [void]$a.Add
porque está bastante claro que la salida no se usará y se descartará.
Personalmente, lo uso ... | Out-Null
porque, como han comentado otros, parece el enfoque más "PowerShellish" en comparación con ... > $null
y [void] ...
. $null = ...
está explotando un específico variable automática y puede ser fácil pasarlo por alto, mientras que los otros métodos lo hacen obvio con una sintaxis adicional que tiene la intención de descartar la salida de una expresión. Porque ... | Out-Null
y ... > $null
al final de la expresión, creo que se comunican efectivamente "toma todo lo que hemos hecho hasta este momento y tíralo", además puedes comentarlos más fácilmente para propósitos de depuración (por ejemplo ... # | Out-Null
), en comparación con poner $null =
o [void]
antes la expresión para determinar qué sucede después de ejecutarlo.
Sin embargo, echemos un vistazo a un punto de referencia diferente: no la cantidad de tiempo que lleva ejecutar cada opción, sino la cantidad de tiempo que lleva averiguar qué hace cada opción . Después de haber trabajado en entornos con colegas que no tenían experiencia con PowerShell o incluso con secuencias de comandos en absoluto, tiendo a tratar de escribir mis secuencias de comandos de una manera que alguien que viene años después podría no entender el lenguaje que está viendo puede tener lucha contra la posibilidad de descubrir qué está haciendo, ya que podrían estar en una posición de tener que apoyarlo o reemplazarlo. Esto nunca se me ha ocurrido como una razón para usar un método sobre los otros hasta ahora, pero imagina que estás en esa posición y usas el help
comando o tu motor de búsqueda favorito para tratar de averiguar quéOut-Null
hace. Obtienes un resultado útil de inmediato, ¿verdad? Ahora intenta hacer lo mismo con [void]
y $null =
. No es tan fácil, ¿verdad?
De acuerdo, suprimir la salida de un valor es un detalle bastante menor en comparación con la comprensión de la lógica general de un script, y solo puede tratar de "tontar" tanto su código antes de cambiar su capacidad de escribir un buen código para un la capacidad del principiante para leer ... código no tan bueno. Mi punto es que es posible que algunos que dominan PowerShell ni siquiera estén familiarizados con ellos [void]
, $null =
etc., y solo porque esos se ejecuten más rápido o tomen menos teclas para escribir, no significa que sean la mejor manera de hacerlo. lo que está tratando de hacer, y solo porque un lenguaje le brinde una sintaxis peculiar no significa que deba usarlo en lugar de algo más claro y mejor conocido. * *
* Supongo que Out-Null
es claro y bien conocido, lo que no sé $true
. Cualquiera que sea la opción que considere más clara y accesible para los futuros lectores y editores de su código (incluido usted mismo), independientemente de la hora de escribir o de ejecutar, esa es la opción que le recomiendo que use.