web-dev-qa-db-fra.com

PowerShell est lent à convertir des entiers en chaînes

J'écris un script PowerShell où de nombreux entiers doivent être convertis en chaînes. J'utilise la méthode ToString pour ce faire, comme dans:

$i = 5
$i.ToString()

Malheureusement, cela semble être très lent (j'ai omis l'avertissement de politique d'exécution):

PS I:\ADCC\Scripting Performance> .\int_to_str.ps1
6.747561
PS I:\ADCC\Scripting Performance> .\int_to_str.py
0.37243021680382793

J'utilise PowerShell 2 et Python 3.

PS I:\ADCC\Scripting Performance> $PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.5485
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1


PS I:\ADCC\Scripting Performance> python --version
Python 3.6.1

Voici le contenu de int_to_str.ps1:

(Measure-Command {
    ForEach($i in 1..1000000){
        $i.ToString()
    }
}).TotalSeconds

Voici le contenu de int_to_str.py:

#!/usr/bin/env python3
import time
start = time.perf_counter()
for i in range(1, 1000000):
    str(i)
print(time.perf_counter() - start)

Comme vous pouvez le voir, les deux scripts convertissent les entiers de 1 à 1 000 000 en chaînes. Cependant, alors que PowerShell prend 6,75 secondes, Python ne prend que 0,37 seconde, ce qui rend Python 18 fois plus rapide. Dans le script PowerShell que j'écris, il faut environ trois heures pour convertir tous les entiers en chaînes, donc une amélioration de la vitesse de 18 fois serait la bienvenue.

Existe-t-il un moyen plus rapide de convertir un int en string dans PowerShell 2?

5
wecsam

Pour répondre à votre question, même dans .NET (qui est ce que vous utilisez avec PowerShell), voici un excellent article sur la conversion de chaîne int-> qui vous intéresse: http://cc.davelozinski.com/c-sharp/le plus rapide-à-convertir-un-int-en-chaîne .

En ce qui concerne les conversions de tableaux d'octets d'AD, voici un test que j'ai fait et avec un cast explicite en [string[]], J'ai presque toujours constaté des gains par rapport à l'utilisation de .tostring (). Les gains variaient de 50% à l'équivalent, mais ils étaient toujours plus rapides:

$s = [adsisearcher]'(&(objectCategory=user)(samaccountname=mysam))'
$r = @($s.FindAll())

(Measure-Command {
    foreach ($b in $r[0].Properties.userpassword[0]) {
        $b.tostring()
    }
}).TotalSeconds

(Measure-Command {
    [string[]]$r[0].Properties.userpassword[0]
}).TotalSeconds
4
thepip3r

J'ai accepté la réponse de @ thepip3r, mais je veux souligner quelques autres solutions possibles à partir des commentaires sur la question deux choses:

  1. Vous pouvez utiliser "$i" Au lieu de $i.ToString(). C'est plus rapide.
  2. Si vous êtes sur PowerShell 2, vous pouvez essayer de télécharger une version plus récente de Windows Management Framework de Microsoft: https://www.Microsoft.com/en-us/download/details.aspx?id=50395

Je vais modifier cela si plus de solutions apparaissent dans les commentaires.

6
wecsam