Une instruction LINQ est-elle plus rapide qu'une boucle 'foreach'?

j'écris un gestionnaire de rendu de maillage et j'ai pensé que ce serait une bonne idée de regrouper tous les maillages qui utilisent le même shader et de les rendre alors que je suis dans ce Shader pass.

j'utilise actuellement une boucle foreach , mais je me suis demandé si L'utilisation de LINQ pourrait me donner une augmentation de performance?

90
demandé sur Stijn 2010-07-01 12:18:16

8 réponses

pourquoi LINQ devrait être plus rapide? Il utilise également des boucles internes.

la plupart du temps, LINQ sera un peu plus lent parce qu'il introduit overhead. N'utilisez pas LINQ si vous vous souciez beaucoup de la performance. Utilisez LINQ parce que vous voulez un code plus court, plus lisible et maintenable.

163
répondu codymanix 2010-07-01 08:21:12

LINQ-to-Objects en général va ajouter quelques frais généraux marginaux (itérateurs multiples, etc). Il doit encore faire les boucles, et a délégué invoque, et devront généralement faire un déréférencement supplémentaire pour obtenir à des variables capturées etc Dans la plupart des codes, ce sera virtuellement indétectable, et plus que permis par le code plus simple à comprendre.

avec d'autres fournisseurs de LINQ comme LINQ-to-SQL, puis puisque la requête peut filtrer sur le serveur , il devrait être beaucoup mieux qu'un plat foreach , mais très probablement vous n'auriez pas fait une couverture "select * from foo" de toute façon , donc ce n'est pas nécessairement une comparaison équitable.

Re PLINQ; le parallélisme peut réduire le temps écoulé , mais le temps CPU total augmentera habituellement un peu en raison de les frais généraux de la gestion de fil, etc.

51
répondu Marc Gravell 2010-07-01 08:23:53

je pense que LINQ est mieux à utiliser sur une boucle foreach , parce qu'il vous donne beaucoup plus propre et facile à comprendre le code. Mais LINQ est plus lent que foreach . Pour en savoir plus, allez à l'article LINQ vs FOREACH vs pour la performance de boucle .

15
répondu Pranay Rana 2015-09-02 20:28:18

LINQ est plus lent maintenant, mais il pourrait devenir plus rapide à un moment donné. La bonne chose à propos de LINQ est que vous n'avez pas à vous soucier de la façon dont il fonctionne. Si une nouvelle méthode est pensée qui est incroyablement rapide, Les gens de Microsoft peuvent l'implémenter sans même vous dire et votre code serait beaucoup plus rapide.

plus important encore, LINQ est juste beaucoup plus facile à lire. Que devrait être une raison suffisante.

14
répondu Jouke van der Maas 2015-09-02 20:32:39

vous pourriez obtenir un boost de performance si vous utilisez LINQ parallèle pour les noyaux multiples. Voir Parallel LINQ (PLINQ) (MSDN).

9
répondu mcintyre321 2015-09-02 20:29:24

il est probablement à noter que la boucle for est plus rapide que la boucle foreach . Donc pour le post d'origine, si vous êtes inquiet de la performance sur un composant critique comme un renderer, utilisez une boucle for .

référence: .NET, qui boucle s'exécute plus rapidement, 'pour' ou 'foreach'?

9
répondu peewee_RotA 2017-05-23 12:34:29

j'étais intéressé par cette question, donc j'ai fait un test tout à l'heure. Utilisation de .net Framework 4.5.2 sur un processeur Intel(R) Core(TM) i3-2328M à 2,20 GHz, 2200 Mhz, 2 Core(S) avec 8 Go de ram tournant sous Microsoft Windows 7 Ultimate.

il semble que LINQ pourrait être plus rapide que pour chaque boucle. Voici les résultats que j'ai eu:

Exists = True
Time   = 174
Exists = True
Time   = 149

Il serait intéressant si certains d'entre vous pouvez copier et coller ce code dans une application console et test bien. Avant de tester avec un objet (employé) j'ai essayé le même test avec des entiers. LINQ était plus rapide là aussi.

public class Program
{
    public class Employee
    {
        public int id;
        public string name;
        public string lastname;
        public DateTime dateOfBirth;

        public Employee(int id,string name,string lastname,DateTime dateOfBirth)
        {
            this.id = id;
            this.name = name;
            this.lastname = lastname;
            this.dateOfBirth = dateOfBirth;

        }
    }

    public static void Main() => StartObjTest();

    #region object test

    public static void StartObjTest()
    {
        List<Employee> items = new List<Employee>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(new Employee(i,"name" + i,"lastname" + i,DateTime.Today));
        }

        Test3(items, items.Count-100);
        Test4(items, items.Count - 100);

        Console.Read();
    }


    public static void Test3(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item.id == idToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test4(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Exists(e => e.id == idToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion


    #region int test
    public static void StartIntTest()
    {
        List<int> items = new List<int>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(i);
        }

        Test1(items, -100);
        Test2(items, -100);

        Console.Read();
    }

    public static void Test1(List<int> items,int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item == itemToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test2(List<int> items, int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Contains(itemToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion

}
2
répondu Theo Kand 2018-06-05 08:09:28

c'est en fait une question assez complexe. Linq rend certaines choses très faciles à faire, que si vous les mettez en œuvre vous-même, vous pourriez trébucher (par exemple linq .Sauf.))( Cela s'applique particulièrement à PLinq, et particulièrement à l'agrégation parallèle telle que mise en œuvre par PLinq.

en général, pour un code identique, linq sera plus lent, en raison des frais généraux de l'invocation des délégués.

si, cependant, vous traitez un large éventail de données, et en appliquant des calculs relativement simples aux éléments, vous obtiendrez une énorme augmentation de performance si:

  1. vous utilisez un tableau pour stocker les données.
  2. vous utilisez une boucle pour accéder à chaque élément (par opposition à foreach ou linq).

    • Note: lors de l'analyse comparative, souvenez - vous tous-si vous utilisez le même tableau/liste pour deux tests consécutifs, le cache CPU fera le deuxième plus rapide. *
1
répondu Adam Brown 2017-12-13 13:27:33