Question \"pipes\" et \"threads\": fonctionnement de powershell

Plus d'informations
il y a 15 ans 1 mois #8813 par bamade
bon c'est une question technique et abstraite sur le fonctionnement de PowerShell
Si je me la pose c'est que je viens des scripts UNIX (pas taper! pas taper! :P )
Un exemple pour comprendre :
[code:1]
# exemple 1 : avec tubage
Get-ChildItem \"C:\Program Files\" -recurse | where {$_.extension -eq \".exe\"}
[/code:1]
et un autre :
[code:1]
#exemple 2: variable de stockage stupide
$fichiers = Get-ChildItem \"C:\Program Files\" -recurse
$fichiers | where {$_.extension -eq \".exe\"}
[/code:1]
Il me semble (mais je peux me tromper) que exemple 1 doit être plus performant/souhaitable si ....
Si chaque code qui fait partie d'un tube a un fonctionnement \"en parallèle\" (Thread natif, ou émulation -green_thread-) [on doit avoir un fonctionnement producteur/consommateur de part et d'autre d'un \"|\": la commande à gauche n'a pas fini de s'exécuter que la commande à droite commence à turbiner]
est-ce important de savoir ça?: oui si on traite un fichier de log avec des millions d'éléments (ça existe).
Donc mesdames et messieurs qui peut me dire comment collaborent les deux parties dans un \"pipe\"?
merci

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 15 ans 1 mois #8815 par Laurent Dardenne
Salut,
berber écrit:

Si je me la pose c'est que je viens des scripts UNIX (pas taper! pas taper! :P )

Je trouve très intéressant d'avoir sur PowerShell des retours de personnes utilisant Unix.
MS n'a rien inventé, Jeffrey Snover et 2-3 de ses collègues ont \"juste\" eu l'idée de passer des objets dans le pipe.
berber écrit:

Il me semble (mais je peux me tromper) que exemple 1 doit être plus performant/souhaitable si ....

Je suis tenté de confirmer, bien que Measure-Command fasse ça mieux que moi.
Mais il faut savoir que sous PS les traitements de masse sur des fichiers peuvent être très, trop, long.
Il y a qq posts à ce sujet sur le forum, mais je ne les ai pas retrouvé.
berber écrit:

Si chaque code qui fait partie d'un tube a un fonctionnement \"en parallèle\" (Thread natif, ou émulation -green_thread-)

Je ne pense pas, sous PS un pipe \"héberge\" deux \"segment\" de pipeline ou une suite d'instructions.
Là il faut voir l'objet pipeline du côté de MSDN, un pipe est exécutée au sein d'un objet Runspace qui ne peut exécuter qu'un seule pipeline à la fois, mais il existe la notion de pipeline imbriquée...
Il faut lire le SDK, voir utiliser Reflector, pour aller plus loin.
berber écrit:

[on doit avoir un fonctionnement producteur/consommateur de part et d'autre d'un \"|\": la commande à gauche n'a pas fini de s'exécuter que la commande à droite commence à turbiner]

C'est ce que l'équipe de PS a formulé dans ses premières présentations (2006) sur ce Shell.
Mais, à mon avis, sans y associer la notion de thread, sous PS tout est adapté, voir le pattern Design Adapter.
berber écrit:

est-ce important de savoir ça?: oui si on traite un fichier de log avec des millions d'éléments (ça existe).

Exact, de toute façons PS te le rappelera indirectement sans que tu le lui demandes.
Hé oui, dans l'adversité PS est sympa ;-)
berber écrit:

Donc mesdames et messieurs qui peut me dire comment collaborent les deux parties dans un \"pipe\"?

Tu peux consulter ce tutoriel , mais je ne suis pas certains qu'il réponde à toutes tes questions.
Ensuite il faut savoir que PS c'est qq fois une boîte noire, ces derniers temps qq personnes sur le forum demandaient où trouver les specs de PowerShell, là où le C# propose + de 500 pages...
Bah c'est un mystère, et la probable réponse de collégiens contemporains ne nous aidera pas.

Pour te dire, même en étant MVP la future V3 reste 'top secret', à mon avis et tout comptes fait, la doc, c'est LE problème sur ce produit !
Bienvenue au club.<br><br>Message édité par: Laurent Dardenne, à: 10/02/11 18:30

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 15 ans 1 mois #8816 par Jacques Barathon
Pour ajouter juste quelques précisions à la réponse déjà très précise de Laurent :

D'une manière générale, le pipe transmet automatiquement à la commande de droite tout objet qu'il reçoit de la commande de gauche.

De ce principe de base, résulte qu'une grande partie de l'efficacité du process dépend de la façon dont les commandes transmettent leurs objets. Si une commande a tendance à ne transmettre ses objets que par lots, voire en un seul lot en fin de traitement, le pipe ne pourra pas faire mieux que d'attendre d'avoir reçu le lot avant de le transmettre.

Maintenant, dans l'exemple que tu donnes, dans les deux cas le pipe reçoit les objets un à un. $fichiers est une collection d'objets reconnue comme telle par PS, il émet donc bien les objets vers le pipe et donc vers la commande suivante au fur et à mesure où il les lit. De ce point de vue-là, cette façon de faire n'est pas moins optimale que la première.

La 2e méthode a surtout comme inconvénients de :

a) monopoliser en mémoire l'espace nécessaire pour stocker $fichiers (alors que dans la 1e méthode, seuls les objets en cours de traitement par le pipe - pour faire simple - monopolisent de la mémoire)

b) différer l'affichage du résultat en toute fin de traitement. En effet, ici le plus long traitement est celui qui consiste à parcourir le disque (get-childitem etc). La partie de lecture des résultats et de filtrage sur les .exe n'est qu'une simple formalité.

On retrouve la même problématique dans les différences entre les deux foreach - le mot-clé foreach et la commande foreach-object :

[code:1]
# mot-clé foreach :

$exe = 0
foreach ($file in get-childitem \&quot;C:\Program Files\&quot; -rec)
{
if ($file.extension -eq \&quot;.exe\&quot;«») {$_; $exe++}
}
\&quot;Nombre de fichiers .exe : {0}\&quot; -f $exe

# Commande foreach-object :

$exe = 0
get-childitem \&quot;C:\Program Files\&quot; -rec | foreach {
if ($_.extension -eq \&quot;.exe\&quot;«») {$_; $exe++}
}
\&quot;Nombre de fichiers .exe : {0}\&quot; -f $exe
[/code:1]

Je ne suis pas convaincu qu'on puisse prédire avec certitude si une méthode sera plus rapide qu'une autre, mais à coup sûr la deuxième consommera moins de mémoire et commencera à afficher ses résultats plus rapidement.

Pour ce qui est de PS et les gros fichiers, le problème est surtout que PS ajoute au contenu des infos propres à son contexte objet. On peut accélérer les choses en passant directement par les classes .NET.

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 15 ans 1 mois #8818 par Arthur
Il n'est pas toujours conseillé d'utiliser les pipe (directement) et un très bon exemple est disponible dans les Powershell Tips de Powershell.com :

When you use Get-Content to read in text files, you may initially be disappointed by its performance. However, Get-Content is slow only because it emits each line to the pipeline as it reads the file, which is time-consuming. You can dramatically speed up reading large text files by adding the parameter -ReadCount 0 to Get-Content. This way, the file is read and only then passed on to the pipeline. Check this out:

Get-Content $env:windir\windowsupdate.log | Where-Object { $_ -like '*successfully installed*' }

$txt = Get-Content $env:windir\windowsupdate.log -ReadCount 0

$txt | Where-Object { $_ -like '*successfully installed*' }


[code:1]Measure-command { $txt = Get-Content $env:windir\windowsupdate.log -ReadCount 0; $txt | Where-Object
{ $_ -like '*successfully installed*' } }
#TotalSeconds : 0,90677

Measure-command { Get-Content $env:windir\windowsupdate.log | Where-Object { $_ -like '*successfully
installed*' } }
#TotalSeconds : 1,1284136
[/code:1]

Il me semble aussi que Powershell a du mal parfois avec les gros traitements, il est conseillé d'utiliser les bonnes classes .NET adaptés, qui sont parfois plus rapides que les cmdlet de base.<br><br>Message édité par: bilbao, à: 10/02/11 23:20

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 15 ans 1 mois #8840 par bamade
donc si je comprends bien l'exécuteur powershell a un comportement d'émulation de Thread: il fait exécuter un ensemble de choses par la partie gauche du pipe puis à droite puis à gauche etc. ça pompe !

@bilbao: je trouve l'exemple cité contre-intuitif. Ou bien l'équipe powershell met en place un mécanisme de bufferisation de lecture dans le fichier, puis nous en fait profiter pour optimiser le pipe ou bien ils ont le devoir d'expliquer pourquoi un stockage dans une variable est plus optimum que de faire un traitement au fil de l'eau. On ne peut pas livrer un \&quot;truc\&quot; technique sans expliquer pourquoi :evil: ! (j'ai développé des interprêtes dans un vie antérieure: un de mes équipiers aurait fait ça je l'aurai mis au pilori!)
- edit: je viens de tester : j'ai exactement l'inverse de ce qui est annoncé les résultats sont conformes à la logique le tube \&quot;pur\&quot; est plus performant! en fait il y a une confusion dans l'exemple ReadCount affecte les performances globales du système de fonctionnement du tube (et donc il faut l'utiliser) mais passer par une variable intermédiaire n'est pas bon. Je soupçonne fortement la doc de ReadCount d'être mal rédigée! (en fait je pense que c'est une option de bufferisation)

@laurent dardenne: le document de specs arrive bientot (ouf!) je l'ai mentionné dans un autre post.

Message édité par: berber, à: 11/02/11 10:00<br><br>Message édité par: berber, à: 11/02/11 10:12

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 15 ans 1 mois #8843 par bamade

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.104 secondes
Propulsé par Kunena