Die PowerShell macht es leider recht einfach ineffizienten Code zu schreiben. Viele Leute benutzen zum Beispiel die +=
Schreibweise um ein Array zu befüllen. Nicht empfehlenswert!
|
|
Mit Measure-Command
können wir messen, wie lange die Ausführung eines Skriptblocks dauert. Bei mir hat die Ausführung des obigen Codes in einer Test-VM über 2 Sekunden benötigt.
Ursache
Die Ursache ist, dass Arrays in PowerShell eigentlich statisch sind. Sie können nicht wirklich um neue Einträge ergänzt werden. Stattdessen wird der Inhalt vom Array kopiert, um den neuen Eintrag ergänzt und in einem neuen Array Objekt gespeichert. Meistens wird das alte Array dann in die gleiche Variable gespeichert, wie das alte Array - deshalb ist dieser Vorgang nicht richtig sichtbar und wird nicht bemerkt.
Alternativen
Es gibt verschiedene Alternativen zur +=
Methode.
Pipeline abfangen
Wenn die Daten im Array nur einmalig angelegt werden sollen, aber nicht verändert werden müssen, dann bevorzuge ich folgendes. Ich nehme meine Variable in der ich das Array speichern möchte, und weise als Inhalt einfach die Rückgabe meiner Schleife zu. Innerhalb der Schleife erfolgt dann gar keine Zuweisung, sondern nur das Ausgabe eines Objekts. Die initialisierung der Variable als Array z.B. per $MeinArray = @()
ist in dem Fall auch nicht nötig.
|
|
Generic List
Wenn die Daten auch geändert werden sollen, ist eine Generic List praktisch. Diese muss per .NET Methode initialisiert werden, was minimal komplizierter als normale PowerShell Cmdlets ist. Aber der Code kann natürlich auch einfach kopiert werden, deshalb spielt es nicht wirklich eine Rolle.
|
|
Ich zeige das auch noch mit mehr Details in einem Video im kostenlosen PowerShell Kurs.
Weitere Alternativen
Es gibt auch noch weitere Alternativen, wie z.B. Hashtables.
|
|
Verbesserungen ab PowerShell 7.5
Ab PowerShell 7.5 (erscheint voraussichtlich im November 2024) ist die Problematik aber etwas entschärft. Die +=
Methode funktioniert dort weitaus schneller als in bisherigen PowerShell Versionen. 100%ig ideal ist sie trotzdem nicht, da weiterhin Daten unnötig im Arbeitsspeicher hin und her kopiert werden müssen.
Geschwindigkeit messen
Mit folgendem Code habe ich die Geschwindigkeit von +=
vs. Generic Lists gemessen. Wobei der Testcode für “Allocated Memory” nur in PowerShell 7 funktioniert, nicht in Windows PowerShell 5.1.
|
|