Nur ein Wort zum Ziehen (falscher) Schlussfolgerungen aus einem der in den Antworten genannten Leistungsmessbefehle. Es gibt eine Reihe von Fallstricken, die berücksichtigt werden sollten, abgesehen von der bloßen Aufrufzeit einer (benutzerdefinierten) Funktion oder eines Befehls.
Sjoemelsoftware
'Sjoemelsoftware' zum niederländischen Wort des Jahres 2015 gewählt
Sjoemelen bedeutet Betrug, und das Wort sjoemelsoftware entstand aufgrund des Volkswagen-Abgasskandals. Die offizielle Definition lautet "Software zur Beeinflussung der Testergebnisse".
Persönlich denke ich, dass " Sjoemelsoftware " nicht immer absichtlich erstellt wurde, um Testergebnisse zu betrügen, sondern möglicherweise aus einer praktischen Situation resultiert, die den unten gezeigten Testfällen ähnelt.
Beispielsweise wird die Verwendung der aufgelisteten Leistungsmessbefehle, Language Integrated Query (LINQ) (1) , häufig als der schnellste Weg bezeichnet, um etwas zu erledigen, und dies ist häufig der Fall, aber sicherlich nicht immer! Jeder, der eine Geschwindigkeitssteigerung um den Faktor 40 oder mehr im Vergleich zu nativen PowerShell-Befehlen misst, misst wahrscheinlich falsch oder zieht eine falsche Schlussfolgerung.
Der Punkt ist, dass einige .Net-Klassen (wie LINQ) eine verzögerte Auswertung verwenden (auch als verzögerte Ausführung bezeichnet (2) ). Das heißt, wenn Sie einer Variablen einen Ausdruck zuweisen, scheint dies fast sofort erledigt zu sein, aber tatsächlich wurde noch nichts verarbeitet!
Lassen Sie vermuten , dass Sie dot-Quelle Ihren . .\Dosomething.ps1
Befehl , die entweder eine Powershell oder ein anspruchsvolleres Linq Ausdruck hat (für die Einfachheit der Erklärung, habe ich direkt die Ausdrücke direkt in die eingebettet Measure-Command
):
$Data = @(1..100000).ForEach{[PSCustomObject]@{Index=$_;Property=(Get-Random)}}
(Measure-Command {
$PowerShell = $Data.Where{$_.Index -eq 12345}
}).totalmilliseconds
864.5237
(Measure-Command {
$Linq = [Linq.Enumerable]::Where($Data, [Func[object,bool]] { param($Item); Return $Item.Index -eq 12345})
}).totalmilliseconds
24.5949
Das Ergebnis scheint offensichtlich zu sein. Der spätere Linq- Befehl ist etwa 40-mal schneller als der erste PowerShell- Befehl. Leider ist es nicht so einfach ...
Lassen Sie uns die Ergebnisse anzeigen:
PS C:\> $PowerShell
Index Property
----- --------
12345 104123841
PS C:\> $Linq
Index Property
----- --------
12345 104123841
Wie erwartet sind die Ergebnisse dieselben, aber wenn Sie genau aufgepasst haben, werden Sie feststellen, dass die Anzeige der $Linq
Ergebnisse viel länger gedauert hat als die $PowerShell
Ergebnisse.
Lassen Sie uns dies speziell messen , indem wir nur eine Eigenschaft des resultierenden Objekts abrufen:
PS C:\> (Measure-Command {$PowerShell.Property}).totalmilliseconds
14.8798
PS C:\> (Measure-Command {$Linq.Property}).totalmilliseconds
1360.9435
Das Abrufen einer Eigenschaft des Objekts dauerte etwa einen Faktor 90 länger als das Abrufen $Linq
des $PowerShell
Objekts, und das war nur ein einzelnes Objekt!
Beachten Sie auch eine andere Gefahr, dass bestimmte Schritte bei einem erneuten Ausführen möglicherweise viel schneller als zuvor angezeigt werden. Dies liegt daran, dass einige der Ausdrücke zwischengespeichert wurden.
Fazit: Wenn Sie die Leistung zwischen zwei Funktionen vergleichen möchten, müssen Sie diese in Ihrem verwendeten Fall implementieren, mit einer neuen PowerShell-Sitzung beginnen und Ihre Schlussfolgerung auf die tatsächliche Leistung der gesamten Lösung stützen.
(1) Für weitere Hintergrundinformationen und Beispiele zu PowerShell und LINQ empfehle ich diese Website: Hochleistungs-PowerShell mit LINQ
(2) Ich denke, es gibt einen geringfügigen Unterschied zwischen den beiden Konzepten, da bei einer verzögerten Bewertung das Ergebnis bei Bedarf berechnet wird Aufgeschobene Ausführung , wenn das Ergebnis berechnet wird, wenn das System inaktiv ist