Solo una parola per trarre conclusioni (errate) da uno qualsiasi dei comandi di misurazione delle prestazioni a cui si fa riferimento nelle risposte. Ci sono una serie di insidie che dovrebbero essere prese in considerazione oltre a guardare al tempo di invocazione nudo di una funzione o comando (personalizzato).
Sjoemelsoftware
'Sjoemelsoftware' ha votato la parola olandese dell'anno 2015
Sjoemelen significa barare, e la parola sjoemelsoftware è nata a causa dello scandalo sulle emissioni di Volkswagen. La definizione ufficiale è "software utilizzato per influenzare i risultati dei test".
Personalmente, penso che " Sjoemelsoftware " non sia sempre stato creato deliberatamente per ingannare i risultati dei test, ma potrebbe derivare da una situazione pratica accomodante simile ai casi di test come mostrato di seguito.
Ad esempio, l'utilizzo dei comandi di misurazione delle prestazioni elencati, Language Integrated Query (LINQ) (1) , è spesso qualificato come il modo più veloce per fare qualcosa e spesso lo è, ma certamente non sempre! Chiunque misura un aumento di velocità di un fattore 40 o superiore rispetto ai comandi nativi di PowerShell, probabilmente sta misurando erroneamente o sta tracciando una conclusione errata.
Il punto è che alcune classi .Net (come LINQ) utilizzano una valutazione lazy (anche definita esecuzione differita (2) ). Ciò significa che quando si assegna un'espressione a una variabile, sembra quasi immediatamente fatto, ma in realtà non ha ancora elaborato nulla!
Supponiamo che tu dot-source il tuo . .\Dosomething.ps1
comando che ha una PowerShell o un'espressione Linq più sofisticata (per semplicità di spiegazione, ho incorporato direttamente le espressioni direttamente in 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
Il risultato sembra ovvio, il successivo comando Linq è circa 40 volte più veloce del primo comando PowerShell . Purtroppo, è non è così semplice ...
Mostriamo i risultati:
PS C:\> $PowerShell
Index Property
----- --------
12345 104123841
PS C:\> $Linq
Index Property
----- --------
12345 104123841
Come previsto, i risultati sono gli stessi ma se hai prestato molta attenzione, avrai notato che ci è voluto molto più tempo per visualizzare i $Linq
risultati, quindi i $PowerShell
risultati.
Misuriamo in modo specifico questo semplicemente recuperando una proprietà dell'oggetto risultante:
PS C:\> (Measure-Command {$PowerShell.Property}).totalmilliseconds
14.8798
PS C:\> (Measure-Command {$Linq.Property}).totalmilliseconds
1360.9435
Ci è voluto circa un fattore 90 in più per recuperare una proprietà $Linq
dell'oggetto quindi l' $PowerShell
oggetto e quello era solo un singolo oggetto!
Notare anche un'altra insidie che se lo fai di nuovo, alcuni passaggi potrebbero apparire molto più velocemente rispetto a prima, questo perché alcune delle espressioni sono state memorizzate nella cache.
In conclusione, se si desidera confrontare le prestazioni tra due funzioni, sarà necessario implementarle nel caso usato, iniziare con una nuova sessione di PowerShell e basare le proprie conclusioni sulle prestazioni effettive della soluzione completa.
(1) Per ulteriori informazioni ed esempi su PowerShell e LINQ, ti consiglio questo sito: PowerShell ad alte prestazioni con LINQ
(2) Penso che ci sia una differenza minore tra i due concetti poiché con una valutazione lenta il risultato viene calcolato quando necessario secondo esecuzione differita se il risultato è calcolato quando il sistema è inattivo