6
votes

Est iénumer

Nous avons connu une certaine lenteur dans notre code ouvrant un formulaire et c'était éventuellement dû à un pour en boucle avec un break qui prenait beaucoup de temps à exécuter. J'ai commuté cela sur un ienumerable.La () et vu le formulaire ouvert très rapidement. J'essaie maintenant de comprendre si ce changement est seul accru de performances ou si elle accédait plus efficacement à la propriété de produits . Si cette implémentation devrait être plus rapide, et si oui, pourquoi?

Mise en œuvre originale: xxx

nouvelle implémentation: xxx


5 commentaires

Avez-vous profilé votre code et vous êtes assuré que la lenteur venait de cela pour la boucle?


Sauf si vous le faites des millions de fois, "plus rapide" n'a pas de sens


Quels sont les produits? Un tableau immuable?


Combien de produits avez-vous? Des millions?


Les produits La propriété est extrêmement lente pour accéder car il fait un traitement lourd (code préexistant). Alors, cette propriété a-t-elle appelé plus de fois dans A pour une boucle que dans le dénombrement de la.


6 Réponses :


4
votes

Je pense qu'ils seraient plus ou moins identiques. Je me réfère habituellement à la série de blogs de Jon Skeet de Jon Skeet pour obtenir une idée de la manière dont fonctionnent les méthodes d'extension. Voici Le message pour tout () et tout ((code> tout (code>

voici la partie principale de tout () de la mise en œuvre de ce post xxx


0 commentaires

8
votes

La première mise en œuvre est légèrement plus rapide forte> (énumération est légèrement plus lente que pour code> boucle). La seconde est beaucoup plus lisible forte>.

mise à jour h2>

la réponse de ODED est éventuellement correcte et bien faite pour la repérer. Le premier est plus lent ici car il implique une rondeau de base de données. Sinon, il est légèrement plus rapide comme je l'ai dit. Em> p>

mise à jour 2 - Preuve h1>

Voici un code simple montrant pourquoi la première est plus rapide: P >

    public static void Main()
    {

        int[] values = Enumerable.Range(0, 1000000).ToArray();

        int dummy = 0;
        Stopwatch stopwatch = new Stopwatch();

        stopwatch.Start();
        for (int i = 0; i < values.Length; i++)
        {
            dummy *= i;
        }
        stopwatch.Stop();
        Console.WriteLine("Loop took {0}", stopwatch.ElapsedTicks);

        dummy = 0;
        stopwatch.Reset();
        stopwatch.Start();
        foreach (var value in values)
        {
            dummy *= value;         
        }
        stopwatch.Stop();
        Console.WriteLine("Iteration took {0}", stopwatch.ElapsedTicks);

        Console.Read();
    }


8 commentaires

Je pense que le légèrement vous faites référence à ce serait ridicule d'optimiser.


Je propose des faits, pas plus. Je préfère personnellement le second.


Cependant, les deux sont loin d'être identiques. Voir l'appel à this.productids.Length qui se produit sur chaque itération de la boucle et non du tout dans la requête linq .


Je pense que foreach et que l'énumération donne au compilateur plus de salle d'optimisation pour travailler avec ... au moins c'est ce que je me souviens de lire efficacement C # Way dans le .NET 1.1 jours.


@Aliostad, je ne suis pas en désaccord, commentant simplement les lecteurs de suivi pour comprendre la portée de la différence de vitesse. ;)


Voir mes mises à jour. J'ai testé et d'abord plus vite (bien que le problème de l'utilisateur semble être autre chose)


Une exécution ne fait pas un profil. Certaines fonctionnent, je parie que la boucle pour la boucle prend plus de tiques. Peut vouloir exécuter ces millions de fois et prendre la moyenne pour profiler avec précision votre preuve.


Faites-le, puis publiez le code. J'ai fait, alors tu pouvais aussi. Parlons des preuves ...



9
votes

Appelez cela une supposition éduquée:

this.ProductIDs.Length


5 commentaires

Donc, la suggestion de prouver que cela consiste à accéder à ProductIDs.length une fois et à la stocker dans une variable locale, puis à mettre cette variable dans votre boucle.


@Adam - Oui, Si C'est la cause de la lenteur.


@ODED Yeah, je me faisais simplement commentaire afin que l'OP puisse voir une possibilité possible d'exercer votre idée.


C'est la seule solution possible, imo. Je soupçonne plus probablement que ce n'est pas le seul changement qui a été fait ou que certains facteurs externes s'appliquent.


C'était en fait le problème dans mon cas, bien que les productides ne provenaient pas d'une base de données. Il y avait beaucoup de code horrible associé à cette propriété. J'ai marqué l'Aliostad comme la réponse puisque elle a répondu à la question plus générale de Will Un. Nany offre une plus grande performance qu'une brève pause. Les produits producteurs seront-ils accessibles plus de fois dans A pour boucle qu'une. Nany?



0
votes

Je pense que la mise en œuvre ci-dessous serait un peu plus rapide que la mise en œuvre de Linq correspondante, mais très mineure si xxx


0 commentaires

0
votes

La différence sera généralement dans l'utilisation de la mémoire puis une vitesse.

Mais généralement, vous devez utiliser la boucle lorsque vous savez que vous utiliserez tous les éléments de la matrice dans d'autres cas, vous devriez essayer d'utiliser tout en faisant.

Je pense que cette solution utilise des ressources minimales xxx


0 commentaires

1
votes

Ce message suppose que productids est une liste ou un tableau. Donc, je parle de linq-to-objets.

LINQ est généralement plus lent mais plus court / plus lisible que le code basé sur la boucle conventionnelle. Un facteur de 2-3 selon ce que vous faites est typique.

Pouvez-vous refactoriser votre code pour faire ceci.productids A hashset ? Ou au moins trier le tableau afin que vous puissiez utiliser une recherche binaire. Votre problème est que vous effectuez une recherche linéaire, ce qui est lent s'il y a de nombreux produits.


0 commentaires