Quelle est la meilleure façon (plus propre) d'ignorer la sortie dans PowerShell? [fermé]

134

Supposons que vous ayez une méthode ou une applet de commande qui renvoie quelque chose, mais que vous ne voulez pas l'utiliser et que vous ne voulez pas le sortir. J'ai trouvé ces deux façons:

Add-Item > $null

[void]Add-Item

Add-Item | Out-Null

Qu'est ce que tu utilises? Quelle est la meilleure approche / la plus propre? Pourquoi?

Hinek
la source
1
comme la version [vide] ... pas encore pour moi, mais je vais essayer de m'en souvenir.
Massif

Réponses:

181

J'ai juste fait quelques tests des quatre options que je connais.

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

Je suggérerais donc que vous n'utilisiez rien d'autre qu'en Out-Nullraison des frais généraux. La prochaine chose importante, pour moi, serait la lisibilité. J'aime un peu me rediriger $nullet m'égaler sur $nullmoi-même. J'avais l'habitude de préférer la diffusion [Void], mais cela peut ne pas être aussi compréhensible lorsque l'on regarde le code ou pour les nouveaux utilisateurs.

Je suppose que je préfère légèrement rediriger la sortie vers $null.

Do-Something > $null

Éditer

Après le commentaire de stej à nouveau, j'ai décidé de faire quelques tests supplémentaires avec des pipelines pour mieux isoler les frais généraux liés à la destruction de la sortie.

Voici quelques tests avec un simple pipeline de 1000 objets.

## 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

Dans ce cas, il Out-Nulla environ 60% de frais généraux et > $nullenviron 0,3% de frais généraux.

Addendum 16/10/2017: Au départ, j'avais oublié une autre option avec Out-Null, l'utilisation du -inputObjectparamètre. En utilisant cela, la surcharge semble disparaître, mais la syntaxe est différente:

Out-Null -inputObject ($(1..1000) | ?{$_ -is [int]})

Et maintenant pour quelques tests avec un simple pipeline de 100 objets.

## 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

Ici encore, il y Out-Nulla environ 60% de frais généraux. Alors > $nullque les frais généraux sont d'environ 4%. Les nombres ici variaient un peu d'un test à l'autre (j'ai couru chacun environ 5 fois et choisi le terrain d'entente). Mais je pense que cela montre une raison claire de ne pas utiliser Out-Null.

JasonMArcher
la source
1
J'utilise généralement VOID pour les choses qui font partie d'une ligne de langage, et out-null si c'est déjà un gros long pipeline de toute façon
klumsy
25
Out-Nullest peut-être au-dessus. Mais ... si le tuyau d'un objet à Out-Null0,076 millisecondes, à mon humble avis, c'est toujours parfaitement bien pour le langage de script :)
stej
1
J'étais un peu dérangé avec cela, et j'obtiens les meilleures performances sur [void] et> $ null en utilisant Out-Null -InputObject ($ (1..1000) |? {$ _ -Is [int]}).
tomohulk
1
Bon point, cela semble n'avoir aucun frais généraux notable.
JasonMArcher
5
S'il est toujours bon d'avoir des repères pour comparer différentes façons d'accomplir quelque chose, n'oublions pas l'autre conclusion qui peut être tirée ici: à moins que vous ne deviez rejeter des valeurs des centaines de milliers de fois, les différences de performances sont négligeables. Et si une milliseconde ici ou là compte vraiment pour vous, vous ne devriez probablement pas utiliser PowerShell en premier lieu. Sans porter de jugement sur le classement des options à cet égard, ce n'est pas nécessairement une mauvaise chose de sacrifier la vitesse pour d'autres qualités telles que la lisibilité et l'expression de l'intention du programmeur.
BACON
22

Je me rends compte que c'est un vieux fil de discussion, mais pour ceux qui prennent la réponse acceptée de @ JasonMArcher ci-dessus comme un fait, je suis surpris que cela n'ait pas été corrigé, beaucoup d'entre nous savent depuis des années que c'est en fait le PIPELINE ajoutant le retard et RIEN à voir avec si c'est Out-Null ou pas. En fait, si vous exécutez les tests ci-dessous, vous verrez rapidement que le même casting "plus rapide" vers [void] et $ void = que pendant des années nous avons tous utilisé en pensant que c'était plus rapide, sont en fait JUSTE COMME LENT et en fait TRÈS LENT quand vous ajoutez N'IMPORTE QUELLE pipelining. En d'autres termes, dès que vous dirigez vers quelque chose, toute la règle de ne pas utiliser out-null va à la poubelle.

Preuve, les 3 derniers tests de la liste ci-dessous. L'horrible Out-null était de 32339,3792 millisecondes, mais attendez - à quel point le lancement de [void] était-il beaucoup plus rapide? 34121,9251 ms?!? WTF? Ce sont de VRAIS # sur mon système, la diffusion vers VOID était en fait PLUS LENTE. Que diriez-vous = $ null? 34217.685ms ..... encore plus lent! Ainsi, comme le montrent les trois derniers tests simples, l'Out-Null est en fait PLUS RAPIDE dans de nombreux cas lorsque le pipeline est déjà utilisé.

Alors, pourquoi est-ce? Facile. C'est et a toujours été à 100% une hallucination que la tuyauterie vers Out-Null était plus lente. C'est cependant que PIPING TO RIEN est plus lent, et ne le savions-nous pas déjà grâce à la logique de base? Nous ne savons peut-être pas COMBIEN plus lentement, mais ces tests racontent certainement une histoire sur le coût d'utilisation du pipeline si vous pouvez l'éviter. Et nous n'avions pas vraiment tort à 100% car il y a un très petit nombre de vrais scénarios où out-null est mauvais. Quand? Lors de l'ajout d'Out-Null, vous ajoutez la SEULE activité de pipeline. En d'autres termes .... la raison pour laquelle une commande simple comme $ (1..1000) | Out-Null comme indiqué ci-dessus a montré vrai.

Si vous ajoutez simplement un tube supplémentaire à Out-String à chaque test ci-dessus, les #s changent radicalement (ou collez simplement ceux ci-dessous) et comme vous pouvez le voir par vous-même, Out-Null devient en fait PLUS RAPIDE dans de nombreux cas:

$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
Collin Chaffin
la source
+1 pour avoir souligné ce point important. En fait, rien n'oblige quiconque à utiliser Out-Nullavec un pipeline, donc la meilleure façon de montrer la surcharge d'un pipeline est de l'invoquer Out-Nullavec et sans lui. Sur mon système, pour 10 000 itérations, j'obtiens 0,576 seconde pour Out-Null -InputObject $GetProcesscontre 5,656 secondes (presque 10 fois plus lent) pour $GetProcess | Out-Null.
BACON
Salut Collin, merci pour votre réponse. J'ai analysé vos échantillons, mais dans tous les lots [void]et j'ai quand $nullmême fait mieux que | Out-Null. Je comprends que c'est à cause du pipeline et que le delta se rétrécit avec les lots ultérieurs, mais sur ma machine, Out-Nullcela ne fonctionne plus rapidement dans aucun des lots.
Hinek
Mais bien sûr, je suis d'accord avec ceux qui affirment que la performance n'est pas tout et que la lisibilité doit également être prise en compte.
Hinek
@Hinek Votre commentaire suggère que vous avez manqué le point de ce que disait Collin. Oui, [void]et $nullfonctionnera mieux que | Out-Null- à cause du |. Essayez Out-Null -InputObject (expression)de comparer.
Jonathan Gilbert le
19

Il existe également l' Out-Nullapplet de commande, que vous pouvez utiliser dans un pipeline, par exemple Add-Item | Out-Null.

Page de manuel pour 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".
Ocaso Protal
la source
Que pensez-vous des résultats du petit test de référence dans la réponse de Jason?
Hinek
Très intéressant, surtout la différence vraiment énorme entre Out-Null et les autres méthodes. Je pense que je vais passer à [void]même si la solution Out-Null semble plus "powershellish".
Ocaso Protal
Je ne sais toujours pas quelle est ma méthode préférée. Même cette énorme différence semble à peine significative comme stej l'a déjà commenté.
Hinek
2
@Hinek [void]semble très clair (bien que ce ne soit pas PowerShellish comme je l'ai dit), vous verrez au début de la ligne qu'il n'y a pas de sortie dans cette ligne. C'est donc un autre avantage, et si vous faites un Out-Null en grande boucle, les performances pourraient être un problème;)
Ocaso Protal
11

J'envisagerais d'utiliser quelque chose comme:

function GetList
{
  . {
     $a = new-object Collections.ArrayList
     $a.Add(5)
     $a.Add('next 5')
  } | Out-Null
  $a
}
$x = GetList

La sortie de $a.Addn'est pas retournée - cela vaut pour tous les $a.Addappels de méthode. Sinon, vous devrez ajouter [void]avant chaque appel.

Dans les cas simples, j'irais avec [void]$a.Addcar il est tout à fait clair que la sortie ne sera pas utilisée et est rejetée.

stej
la source
2

Personnellement, j'utilise ... | Out-Nullparce que, comme d'autres l'ont commenté, cela ressemble à l'approche plus «PowerShellish» par rapport à ... > $nullet [void] .... $null = ...exploite une variable automatique spécifique et peut être facile à ignorer, alors que les autres méthodes montrent clairement avec une syntaxe supplémentaire que vous avez l'intention de supprimer la sortie d'une expression. Parce que ... | Out-Nullet ... > $nullvenir à la fin de l'expression, je pense qu'ils communiquent efficacement "prenez tout ce que nous avons fait jusqu'à présent et jetez-le", plus vous pouvez les commenter plus facilement à des fins de débogage (par exemple ... # | Out-Null), par rapport à la mise $null =ou [void] avant l'expression pour déterminer ce qui se passe après son exécution.

Examinons cependant un point de repère différent: non pas le temps nécessaire pour exécuter chaque option, mais le temps nécessaire pour déterminer ce que fait chaque option . Ayant travaillé dans des environnements avec des collègues qui n'étaient pas du tout expérimentés avec PowerShell ou même avec des scripts, j'ai tendance à essayer d'écrire mes scripts de manière à ce que quelqu'un venant des années plus tard et qui ne comprenne même pas la langue qu'il regarde puisse avoir un lutter contre la chance de comprendre ce qu'il fait, car ils pourraient être en mesure de le soutenir ou de le remplacer. Cela ne m'est jamais venu à l'esprit comme une raison d'utiliser une méthode par rapport aux autres jusqu'à présent, mais imaginez que vous êtes dans cette position et que vous utilisez la helpcommande ou votre moteur de recherche préféré pour essayer de savoir ce queOut-NullEst-ce que. Vous obtenez un résultat utile immédiatement, non? Maintenant, essayez de faire de même avec [void]et $null =. Pas si facile, n'est-ce pas?

Certes, la suppression de la sortie d'une valeur est un détail assez mineur par rapport à la compréhension de la logique globale d'un script, et vous ne pouvez essayer de "baisser" votre code qu'avant d'échanger votre capacité à écrire du bon code contre un capacité du novice à lire ... du code pas si bon Ce que je veux dire, c'est qu'il est possible que certains qui maîtrisent PowerShell ne soient même pas familiers avec [void], $null =etc., et ce n'est pas parce que ceux-ci peuvent s'exécuter plus rapidement ou prendre moins de frappes pour taper que c'est la meilleure façon de faire. ce que vous essayez de faire, et ce n'est pas parce qu'un langage vous donne une syntaxe excentrique que vous devriez l'utiliser au lieu de quelque chose de plus clair et de mieux connu. *

* Je présume que Out-Nullc'est clair et bien connu, ce que je ne sais pas $true. Quelle que soit l'option que vous jugez la plus claire et la plus accessible aux futurs lecteurs et éditeurs de votre code (y compris vous-même), quel que soit le temps de saisie ou d'exécution, c'est l'option que je vous recommande d'utiliser.

BACON
la source