Il blog di Sandro Rizzetto

Comparare SkipWhile e Where con BenchmarkDotNet

 

Dall'ottimo account Twitter di Fabio Ramoni (@developer_fabio) ho appreso dell'esistenza del metodo Linq SkipWhile (e ovviamente del suo compare TakeWhile) che similmente al fratello famoso Skip, salta un certo numero di oggetti in una collection indicando però una condizione e non un numero fisso di items. 

Es.

var list = new List<int>() { 1, 2, 3, 4, 5 };
var skipped = list.SkipWhile(x => x < 3);

Molto più interessante il secondo overload che permette di passare alla Func anche l'index dell'elemento corrente. Es.

int[] amounts = { 5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500 };
IEnumerable<int> query = amounts.SkipWhile((amount, index) => amount > index * 1000);
// => 4000, 1500,  5500

Il primo elemento estratto sarà 4000 (perché il primo a non essere maggiore di 1000*index che è 5), i successivi vengono comunque stampati in quanto in rimanenti elementi dopo che la condizione non viene soddisfatta vengono comunque presi.

Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.

Non avendo subito capito questa cosa, mi chiedevo cosa ci fosse di differenza a usare una Where

var filtered = list.Where(x => x >= 3);

Se però la collection è ordinata secondo il campo su cui vogliamo filtrare o skippare, le due istruzioni sono equivalenti. Anche in termini di performance?

Visto che (sempre nelle mie produttive vacanze di Natale) ho da poco scoperto la libreria BenchmarkDotNet, quale occasione migliore per giocarci con un esempio concreto? Ovvero testare quanto sia più veloce/lento lo SkipWhile nei confronti della Where?

Senza fare un benchmark mi aspetterei che se gli elementi da skippare saranno pochi vincerà la SkipWhile, al contrario la Where. Ma di quanto? E se sono 50/50?

Non voglio entrare nei dettagli di come impostare il benchmark perché ci sono molti video tutorial su Youtube (es. qui e qui) e anche la documentazione ufficiale è bene fatta.

Ho provato a creare una collection di N oggetti "persona" con un campo età ed a skippare/filtrare per varie età vicine e lontane ai limiti.

Il risultato NON conferma la mia ipotesi iniziale, la where è sempre più performante da 3 a 4 volte. La grandezza della collection non cambia i risultati che sono abbastanza lineari.

Come diciamo sempre ai nostri prospect riguardo ai nostri sistemi di valutazione della performance atletica, "if you're not assessing, you're guessing!"

Il codice lo trovate qui.

E qui i risultati:

 

Aggiungi Commento

Copyright © 1997-2024 Sandro Rizzetto | All Rights Reserved | Riproduzione delle fotografie vietata | Powered by me