2010-12-10 41 views
0

application Silverlight 4 en utilisant WCF RIA Services deLINQ Performance Question: Somme prend plus avec moins d'enregistrements

J'ai une page avec un ComboBox et un TabControl. Chaque TabItem a une commande usercontrol qui affiche un contrôle RAD Chart. ComboBox contient des éléments utilisés pour filtrer les données que les contrôles utilisateur affichent dans les graphiques. Lorsque la sélection ComboBox change, la page met à jour une collection d'entités détenues sur une propriété d'une classe instance/singleton. Les commandes utilisateur sont notifiées du changement et elles accèdent à la collection mise à jour d'entités à donner au contrôle graphique. Tout fonctionne. Lorsque la sélection ComboBox change, les contrôles utilisateur affichent un sous-ensemble des données sélectionnées en fonction de l'élément sélectionné ComboBox.

Ce qui m'a dérouté, c'est le temps qu'il faut pour parcourir la collection d'entités tout en préparant les valeurs qui sont transmises au contrôle de graphique. Le graphique affiche 12 mois de données, donc je l'itère 12 fois et j'utilise une requête LINQ pour obtenir une somme sur une propriété des objets de la collection. J'ai isolé le problème de performances à la seule requête LINQ qui effectue la Somme:

Decimal sum = myCollection.Where(m => m.CreationDate.Month == month).Sum(m => (m.SalePrice ?? 0)); 

Cette ligne de code peut parfois prendre plus d'une seconde pour exécuter. Ce n'est pas horrible, mais je répète 12 mois, donc cette ligne de code est exécutée 12 fois.

Voici le kicker ...

L'option supérieure ComboBox est 'tous les dossiers'. Donc, dans mon exemple de test, la première fois que la ligne de code ci-dessus est utilisée pour obtenir une 'somme', la collection a plus de 500 enregistrements. Il retourne la Somme en .2 secondes. Je change le ComboBox à une sélection qui filtre les résultats de manière à ce que la collection ne contienne que 80 enregistrements. Rappelez-vous, ce n'est pas un ensemble de dossiers totalement différent, c'est juste un sous-ensemble des 500 qui répondent à un autre critère. La ligne de code ci-dessus prend 1,2 secondes pour s'exécuter. Lorsque je demande une somme à partir de 500 enregistrements, cela prend 0,2 seconde. Quand je demande une somme de 80 enregistrements, cela prend 1,2 secondes.

Ce qui pourrait causer cela?

Merci,

Répondre

2

Comment filtrer pour créer le sous-ensemble? Est-ce que "Collection" est une requête Linq elle-même, qui est deffered en exécution jusqu'à cette ligne? Si c'est le cas, la différence de vitesse que vous voyez pourrait être l'application de la logique de filtrage.

Une possibilité générale pour rendre ceci plus rapide serait de calculer tous les 12 nombres en un seul passage. Cela est assez facile en utilisant l'opérateur GroupBy Linq:

var AllSums = Collection.GroupBy(m=>m.CreationData.Month).ToDictionary(g => g.Key, g => g.Sum(m => m.SalePrice ?? 0)); 
var JanuarySum = AllSums[January]; 

Cela devrait surpasser 12 boucles complètement séparées.

Edit: Voici une bonne description de l'exécution différée: Linq and Deferred Execution

+0

Je l'appelle un sous-ensemble, parce que je tiens à souligner que ce n'est pas un totalement différent de 80 dossiers, mais plutôt seulement 80 enregistrements de 500 initial Je vois ce que vous voulez dire par le potentiel du filtre différé jusqu'à l'exécution de cette ligne. Voici où ma compréhension LINQ s'arrête. Si je fais un Count() sur la collection (comme je suis avant la ligne collée ci-dessus), et qu'il contient 80 enregistrements, le même filtre sera-t-il répété à chaque fois que je totalise contre la collection? – Roger

+0

Uhg .. continuez à écrire avant d'avoir fini de taper mon commentaire ... Pour créer la collection, je crée un nouvel IEnumerable et le place comme un autre collecion.Where (... et quelques autres where .Cette nouvelle instance d'une collection a-t-elle un potentiel d'exécution différée sur les clauses where? La première fois que vous interrogez la collection, si elle a été différée, sera-t-elle différée chaque fois que vous l'interrogez? Merci ... Et je vais essayer votre clause GroupBy, après avoir compris le problème de perf. – Roger

+0

Si je crée une nouvelle collection et que je la remplis à l'aide d'une requête LINQ provenant d'une autre collection, y a-t-il des problèmes d'exécution retardés sur la nouvelle collection? – Roger