2011-09-12 13 views
6

Prendere come esempio la seguente query LINQ. Si prega di non commentare il codice stesso come ho appena digitato per aiutare con questa domanda.Query di raggruppamento LINQ di grandi dimensioni, cosa accade dietro le quinte

La seguente query LINQ utilizza un "gruppo per" e calcola le informazioni di riepilogo. Come puoi vedere ci sono numerosi calcoli che vengono eseguiti sui dati ma quanto è efficiente LINQ dietro le quinte.

var NinjasGrouped = (from ninja in Ninjas 
    group pos by new { pos.NinjaClan, pos.NinjaRank } 
    into con 
    select new NinjaGroupSummary 
    { 
     NinjaClan = con.Key.NinjaClan, 
     NinjaRank = con.Key.NinjaRank, 
     NumberOfShoes = con.Sum(x => x.Shoes), 
     MaxNinjaAge = con.Max(x => x.NinjaAge), 
     MinNinjaAge = con.Min(x => x.NinjaAge), 
     ComplicatedCalculation = con.Sum(x => x.NinjaGrade) != 0 
     ? con.Sum(x => x.NinjaRedBloodCellCount)/con.Sum(x => x.NinjaDoctorVisits) 
     : 0, 
    ListOfNinjas = con.ToList() 
    }).ToList(); 
  1. Quante volte è l'elenco dei 'Ninjas' essere iterato sopra al fine di calcolare ciascuno dei valori?
  2. Sarebbe più rapido impiegare un ciclo foreach per accelerare l'esecuzione di tale query?
  3. Aggiungendo ".AsParallel()" dopo Ninjas si ottengono miglioramenti delle prestazioni?
  4. Esiste un modo migliore per calcolare le informazioni di scadenza per l'elenco?

Qualsiasi consiglio è apprezzato poiché utilizziamo questo tipo di codice in tutto il nostro software e mi piacerebbe davvero ottenere una migliore comprensione di ciò che LINQ sta facendo sotto il cofano (per così dire). Forse c'è un modo migliore?

+1

+1 per i ninja. –

+0

È importante sapere se 'Ninjas' è un' IEnumerable' o un 'IQueryable'. Se precedente, verrebbe enumerato esattamente una volta. In quest'ultimo caso, non c'è nessuna enumerazione di cui parlare; la query è compilata, ad esempio, direttamente in SQL; il raggruppamento è fatto dal DBMS e l'unica cosa enumerata in C# è il set di risultati. –

+0

'Ninjas' è un elenco in memoria, IEnumerable. – Belinda

risposta

6

Supponendo che questo è un query LINQ to Objects:

  • Ninjas è solo ripetuti su una sola volta; i gruppi sono incorporati in elenchi concreti interni, che vengono quindi ripetuti più volte (una volta per aggregazione).
  • L'utilizzo di un ciclo foreach quasi certamente non accelera le cose - si potrebbe trarre un ulteriore vantaggio dalla coerenza della cache (poiché ogni volta che si esegue iterazione su un gruppo, probabilmente sarà necessario recuperare i dati da una cache di livello superiore o dalla memoria principale) ma dubito fortemente che sarebbe significativo. L'aumento del dolore nella sua attuazione probabilmente sarebbe significativo però :)
  • Utilizzando AsParallelforza accelerare le cose - sembra piuttosto facilmente parallelizzabile. Vale la pena provare ...
  • Non c'è un modo molto migliore per LINQ to Objects, per essere onesti. Sarebbe bello poter eseguire l'aggregazione mentre si sta raggruppando, e le Reactive Extensions ti permetterebbero di fare qualcosa del genere, ma per il momento questo è probabilmente l'approccio più semplice.

Si potrebbe desiderare di avere uno sguardo al GroupBy post in my Edulinq blog series per maggiori dettagli su una possibile implementazione.

+1

Grazie Jon, in effetti questa è una query LINQ to Objects. Puoi ampliare il tuo commento "L'uso di un ciclo foreach quasi certamente non accelererebbe le cose", non vedo come ciò sia vero se le liste concrete interne vengono ripetute (potenzialmente) numerose volte? – Belinda

+0

@Belinda: Beh, stai elaborando la stessa quantità di dati: ti limiterai a tenere traccia delle cose in modo leggermente diverso. Immagino che trarrai vantaggio dalla coerenza della cache un po ', ma dubito fortemente che sarebbe significativo. Modificherà per renderlo più chiaro. –

+0

@JonSkeet Non sarebbe un singolo ciclo for su 'con' accelerare le cose dato che sarebbe in grado di calcolare tutti i valori aggregati in un colpo solo? (Ora ogni aggregato ha bisogno di iterare 'con' da solo) – Magnus

Problemi correlati