66 votes

Devrait LINQ être évitée car elle est lente?

J'ai avait été dit que depuis .net, linq est si lent, nous ne devrions pas l'utiliser et je me demandais quelqu'un d'autre a venir avec la même conclusion, et l'exemple est:

Pris 1443ms faire 1000000000 compare non-LINQ.
Pris 4944ms faire 1000000000 compare avec LINQ.
(243% plus lent)

le non-LINQ code:

for (int i = 0; i < 10000; i++)
{
    foreach (MyLinqTestClass1 item in lst1) //100000 items in the list
    {
        if (item.Name == "9999")
        {
            isInGroup = true;
            break;
        }
    }
}

Pris 1443ms faire 1000000000 compare non-LINQ.

Code LINQ:

for (int i = 0; i < 10000; i++)  
    isInGroup = lst1.Cast<MyLinqTestClass1>().Any(item => item.Name == "9999");  

Pris 4944ms faire 1000000000 compare avec LINQ.

Je suppose que c'est possible d'optimiser le code LINQ mais l'idée était que le son facilement à être vraiment lent LINQ code et étant donné qu'il ne devrait pas être utilisé. Étant donné que LINQ est lent, puis il suivra aussi que PLINQ est lente et NHibernate LINQ serait lente de sorte que tout type sur LINQ déclaration ne doit pas être utilisé.

Quelqu'un d'autre a constaté que LINQ est lent qui le souhaitaient, ils n'ont jamais utilisé de, ou en serions-nous faire un trop général commotion cérébrale basée sur des critères comme cela?

256voto

Eric Lippert Points 300275

Devrait Linq être évitée en raison de sa lente?

Pas de. Elle devrait être évitée si il est pas assez rapide. Lent et pas assez rapide ne sont pas du tout la même chose!

Lent est pas pertinent pour vos clients, votre gestion et vos parties prenantes. Pas assez rapide est extrêmement pertinent. Ne jamais mesurer comment rapide est quelque chose; qui vous dit rien que vous pouvez utiliser à la base d'une décision d'affaires. Mesurer le degré de proximité avec d'être acceptable pour le client il est. Si elle est acceptable, alors arrêter de dépenser de l'argent sur le rendant plus rapide; c'est déjà bien assez.

L'optimisation de la Performance est cher. L'écriture de code de sorte qu'il peut être lu et entretenus par d'autres est cher. Ces objectifs sont souvent en opposition les uns aux autres, afin de passer vos parties prenantes de l'argent de façon responsable, vous avez pour vous assurer que vous êtes seulement un temps précieux et d'efforts à faire de l'optimisation des performances sur des choses qui sont pas assez rapide.

Vous avez trouvé une artificielle, irréaliste de référence situation où LINQ code est plus lent que sur une autre façon d'écrire le code. Je vous assure que vos clients de soins n'est pas un peu sur la vitesse de votre irréaliste de référence. Ils ont en charge uniquement si le programme que vous êtes de livraison est trop lent pour eux. Et je vous assure, la gestion de votre soucis n'est pas un peu à ce sujet (si elles sont compétentes); ils se soucient de savoir combien d'argent vous serez en mesure de dépenser inutilement de faire des trucs qui est assez rapide unnoticably plus rapide, et de rendre le code plus cher de lire, de comprendre, et de maintenir dans le processus.

160voto

Jon Skeet Points 692016

Pourquoi êtes-vous à l'aide de Cast<T>()? Vous n'avez pas donné assez de code pour vraiment juger de l'indice de référence, en gros.

Oui, vous pouvez utiliser LINQ pour écrire lente code. Devinez quoi? Vous pouvez écrire lent non-LINQ code, trop.

LINQ grandement le sida de l'expressivité du code portant sur les données... et il n'est pas difficile d'écrire du code qui fonctionne bien, aussi longtemps que vous prenez le temps de comprendre LINQ pour commencer.

Si quelqu'un dit à moi de ne pas utiliser LINQ (surtout LINQ to Objects) pour la perception des raisons de vitesse je ris dans leur visage. Si ils sont venus avec un goulot d'étranglement et a dit, "Nous pouvons rendre cela plus rapidement par la non-utilisation de LINQ dans cette situation, et en voici la preuve", alors que c'est une toute autre affaire.

86voto

Aaronaught Points 73049

Peut-être que j'ai manqué quelque chose, mais je suis sûr que tes repères sont éteints.

J'ai testé avec les méthodes suivantes:

  • L' Any méthode d'extension ("LINQ")
  • Un simple foreach boucle (votre "optimisé" de la méthode)
  • À l'aide de l' ICollection.Contains méthode
  • L' Any méthode d'extension à l'aide d'une optimisation de structure de données (HashSet<T>)

Voici le code de test:

class Program
{
    static void Main(string[] args)
    {
        var names = Enumerable.Range(1, 10000).Select(i => i.ToString()).ToList();
        var namesHash = new HashSet<string>(names);
        string testName = "9999";
        for (int i = 0; i < 10; i++)
        {
            Profiler.ReportRunningTimes(new Dictionary<string, Action>() 
            {
                { "Enumerable.Any", () => ExecuteContains(names, testName, ContainsAny) },
                { "ICollection.Contains", () => ExecuteContains(names, testName, ContainsCollection) },
                { "Foreach Loop", () => ExecuteContains(names, testName, ContainsLoop) },
                { "HashSet", () => ExecuteContains(namesHash, testName, ContainsCollection) }
            },
            (s, ts) => Console.WriteLine("{0, 20}: {1}", s, ts), 10000);
            Console.WriteLine();
        }
        Console.ReadLine();
    }

    static bool ContainsAny(ICollection<string> names, string name)
    {
        return names.Any(s => s == name);
    }

    static bool ContainsCollection(ICollection<string> names, string name)
    {
        return names.Contains(name);
    }

    static bool ContainsLoop(ICollection<string> names, string name)
    {
        foreach (var currentName in names)
        {
            if (currentName == name)
                return true;
        }
        return false;
    }

    static void ExecuteContains(ICollection<string> names, string name,
        Func<ICollection<string>, string, bool> containsFunc)
    {
        if (containsFunc(names, name))
            Trace.WriteLine("Found element in list.");
    }
}

Ne vous inquiétez pas sur le fonctionnement interne de l' Profiler classe. Il fonctionne juste l' Action dans une boucle et utilise un Stopwatch du temps. Elle fait également en sorte d'appeler GC.Collect() avant chaque test afin d'éliminer autant de bruit que possible.

Voici les résultats:

      Enumerable.Any: 00:00:03.4228475
ICollection.Contains: 00:00:01.5884240
        Foreach Loop: 00:00:03.0360391
             HashSet: 00:00:00.0016518

      Enumerable.Any: 00:00:03.4037930
ICollection.Contains: 00:00:01.5918984
        Foreach Loop: 00:00:03.0306881
             HashSet: 00:00:00.0010133

      Enumerable.Any: 00:00:03.4148203
ICollection.Contains: 00:00:01.5855388
        Foreach Loop: 00:00:03.0279685
             HashSet: 00:00:00.0010481

      Enumerable.Any: 00:00:03.4101247
ICollection.Contains: 00:00:01.5842384
        Foreach Loop: 00:00:03.0234608
             HashSet: 00:00:00.0010258

      Enumerable.Any: 00:00:03.4018359
ICollection.Contains: 00:00:01.5902487
        Foreach Loop: 00:00:03.0312421
             HashSet: 00:00:00.0010222

Les données sont très cohérente et raconte l'histoire suivante:

  • Naïvement à l'aide de l' Any méthode d'extension est d'environ 9% plus lent que naïvement à l'aide d'un foreach boucle.

  • À l'aide de la méthode la plus appropriée (ICollection<string>.Contains) avec un unoptimized structure de données (List<string>) est environ 50% plus rapide que naïvement à l'aide d'un foreach boucle.

  • À l'aide d'une optimisation de structure de données (HashSet<string>) souffle complètement l'une des méthodes hors de l'eau en termes de performances.

Je n'ai aucune idée de l'endroit où vous avez obtenu 243%. Ma conjecture est qu'il a quelque chose à faire avec tout ce casting. Si vous utilisez un ArrayList alors non seulement vous à l'aide d'un unoptimized structure de données, vous êtes en utilisant une grande partie obsolète structure de données.

Je peux prévoir ce qui vient ensuite. "Ouais, je sais que vous pouvez l'optimiser un peu mieux, mais c'était juste un exemple pour comparer la performance de LINQ vs non-LINQ."

Ouais, mais si vous ne pouvait pas encore être approfondie dans votre exemple, comment peut-on s'attendre à l'être approfondie dans le code de production?

La ligne de fond est:est-ce

Comment vous l'architecte et la conception de votre logiciel est considérablement plus important que ce que les outils spécifiques que vous utilisez et quand.

Si vous exécutez dans les goulets d'étranglement de performance - qui est tout aussi susceptible de se produire avec LINQ vs sans - puis à les résoudre. Eric suggestion de traitement automatisé de tests de performance est excellente; qui va vous aider à identifier les problèmes précoce de sorte que vous pouvez les résoudre correctement - pas en fuyant un outil étonnant qui vous fait 80% plus productif, mais il arrive à subir une < 10% de la performance, mais en fait, l' enquête sur la question et à venir avec une solution qui peut booster vos performances par un facteur de 2, ou 10, ou 100 ou plus.

La création des applications de haute performance n'est pas à propos de l'utilisation du droit de bibliothèques. C'est à propos de profilage, à faire de bons choix de conception, et la rédaction d'un bon code.

15voto

STW Points 15326

Est LINQ un monde réel goulot d'étranglement (soit effectuer l'ensemble ou de la performance perçue de la demande)?

Sera votre application effectue cette opération sur 1 000 000 000 d'+ enregistrements dans le monde réel? Si oui, alors vous pourriez envisager des solutions de rechange--si non, alors c'est comme dire "on ne peut pas acheter cette berline familiale car elle permet de ne pas conduire à 180+ MPH".

Si c'est "juste lent", alors ce n'est pas une très bonne raison... par ce raisonnement, vous devriez être en écrivant tout en asm/C/C++ et C# doit être hors de la table pour être "trop lent".

12voto

snemarch Points 3328

Tout prématurée pessimization est (à mon humble avis) aussi mauvais que l'optimisation prématurée, vous ne devriez pas écarter toute une technologie basée sur la vitesse absolue, sans prendre d'utilisation en considération. Oui, si vous êtes en train de faire quelques très lourd arithmétique et c'est un goulot d'étranglement, LINQ pourrait être problématique profil.

Un argument que vous pourriez utiliser en faveur de LINQ, c'est que, tandis que vous pouvez probablement surpasser avec manuscrites code, le LINQ version pourrait être plus clair et plus facile à maintenir - en plus, il y a l'avantage de PLINQ par rapport à manuel complexe de parallélisation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X