Tylko słowo na temat wyciągania (niepoprawnych) wniosków z dowolnych poleceń pomiaru wydajności, o których mowa w odpowiedziach. Istnieje szereg pułapek, które należy wziąć pod uwagę oprócz patrzenia na sam czas wywołania (niestandardowej) funkcji lub polecenia.
Sjoemelsoftware
„Sjoemelsoftware” przegłosowało holenderskie słowo roku 2015
Sjoemelen oznacza oszustwo, a słowo sjoemelsoftware powstało z powodu skandalu emisyjnego Volkswagena. Oficjalna definicja to „oprogramowanie używane do wpływania na wyniki testów”.
Osobiście uważam, że „ Sjoemelsoftware ” nie zawsze jest celowo tworzone w celu oszukiwania wyników testów, ale może wynikać z przystosowania się do praktycznej sytuacji podobnej do przypadków testowych, jak pokazano poniżej.
Jako przykład, za pomocą poleceń wymienionych pomiarów wydajności, LINQ (LINQ) (1) , jest często kwalifikowane jako na czczo sposób coś zrobić i to często jest, ale na pewno nie zawsze! Każdy, kto mierzy wzrost prędkości o współczynnik 40 lub więcej w porównaniu z natywnymi poleceniami PowerShell, prawdopodobnie nieprawidłowo mierzy lub wyciąga błędne wnioski.
Chodzi o to, że niektóre klasy .Net (jak LINQ) używają leniwej oceny (zwanej także odroczonym wykonaniem (2) ). Oznacza to, że przypisanie wyrażenia do zmiennej wydaje się prawie natychmiastowe, ale w rzeczywistości nic jeszcze nie przetworzyło!
Załóżmy, że wklejasz swoje . .\Dosomething.ps1
polecenie, które ma albo PowerShell albo bardziej wyrafinowane wyrażenie Linq (dla ułatwienia wyjaśnienia, bezpośrednio osadziłem wyrażenia bezpośrednio w 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
Wynik wydaje się oczywisty, późniejsze polecenie Linq jest około 40 razy szybsze niż pierwsze polecenie PowerShell . Niestety nie jest to takie proste ...
Wyświetlmy wyniki:
PS C:\> $PowerShell
Index Property
----- --------
12345 104123841
PS C:\> $Linq
Index Property
----- --------
12345 104123841
Zgodnie z oczekiwaniami wyniki są takie same, ale jeśli zwrócisz szczególną uwagę, zauważysz, że wyświetlenie $Linq
wyników zajęło dużo więcej czasu niż $PowerShell
wyników.
Zmierzmy to konkretnie , po prostu pobierając właściwość wynikowego obiektu:
PS C:\> (Measure-Command {$PowerShell.Property}).totalmilliseconds
14.8798
PS C:\> (Measure-Command {$Linq.Property}).totalmilliseconds
1360.9435
Pobranie właściwości obiektu niż obiektu zajęło około 90 razy dłużej i był to tylko jeden obiekt!$Linq
$PowerShell
Zauważ też inną pułapkę, że jeśli zrobisz to ponownie, niektóre kroki mogą pojawić się znacznie szybciej niż wcześniej, ponieważ niektóre wyrażenia zostały buforowane.
Podsumowując, jeśli chcesz porównać wydajność między dwiema funkcjami, musisz zaimplementować je w używanym przypadku, rozpocząć od nowej sesji PowerShell i oprzeć swój wniosek na rzeczywistej wydajności kompletnego rozwiązania.
(1) Aby uzyskać więcej informacji na temat PowerShell i LINQ, i przykładów, polecam tihis site: High Performance PowerShell with LINQ
(2) Myślę, że istnieje niewielka różnica między tymi dwiema koncepcjami, ponieważ w przypadku leniwej oceny wynik jest obliczany, gdy jest potrzebny, w odniesieniu do odroczone wykonanie , gdy wynik jest obliczany, gdy system jest bezczynny