Mittendrin.

Zurück

Flurfunk der eXperts.

Hier erfahren Sie mehr über eXperts, Technologien und das wahre Leben in der SDX.

Performancefalle Linq

06.07.201108:37 Uhr , Sven Matzen

LINQ macht viele Dinge im C#-Code einfacher, ausdrucksvoller und eleganter. Aber manchmal bietet es doch Stolpersteine, die eine Fehlersuche oder das Suchen von schlecht performanten Code stark verkomplizieren.

Häufig sind die Gründe dafür zwar generell bekannt, werden aber nicht ausreichend bei der Arbeit mit LINQ beachtet.

Nehmen wir den folgenden Code:

// let's generate some items in a simple list 

var myEnum = new List<string> { "a", "b", "c", "d", "e" };

// now we order the list 

var myOrderedList = from x in myEnum orderby x.CustomOrderBy() select x;

Wir legen also eine Liste an und fragen alle Elemente in einer bestimmten Reihenfolge ab. Relativ simples Code-Konstrukt. Um nun mit den Daten etwas zu machen und über das Hello-World-Szenario hinaus zu gehen, fragen wir unsere sortierte Liste mit einem where-Statement ab und lassen uns das erste Element geben – das Ganze bringen wir noch in einem Loop unter:

// lets enumerate the list items 

foreach (var listItem in myEnum)   

{

  // for each of the elements filter the list for all items 

  // "less" than the current item 

  var myItem = (from x in myOrderedList

                where x.CustomWhere(listItem)

                select x).FirstOrDefault();   

  Console.WriteLine(myItem);

}

Die Methoden CustomWhere und CustomOrderBy sind trivial in Form von Extension Methods implementiert und nur für das Zählen der Aufrufe gedacht:

public static class Extensions

{

    private static int WhereCounter;

    private static int OrderByCounter;

 

    public static string CustomOrderBy(this string value)

    {

        OrderByCounter++;

        Console.WriteLine("CustomOrderBy: {0} Aufrufe", OrderByCounter);

        return value;

    }

 

    public static bool CustomWhere(this string value, string compareto)

    {

        WhereCounter++;

        Console.WriteLine("CustomWhere:   {0} Aufrufe", WhereCounter);

        return value == compareto;

    }

}

Wie im Code zu sehen, habe ich zwei Methoden in der Sortierung und in der Filterung eingesetzt – diese zählen einfach die Aufrufe, so dass wir überprüfen können, wie die Linq-Statements ausgeführt werden:

CustomOrderBy: 25 Aufrufe
CustomWhere:   15 Aufrufe

Whow! 25 Aufrufe für CustomOrderBy – würde Linq mit einem simplen Sortierungs-Algorithmus die das orderby-Statement ausführen, wäre 5 zu erwarten … es gibt ja nur eine Stelle, an der einmalig die Sortierung durchgeführt wird.

Aber: das LINQ-Statement iteriert und sortiert eben NICHT die Liste; es generiert eine Klasse, welche eine sortierte IEnumerable<string> zurück liefert. Also wird die LINQ-Abfrage jedes Mal durchgeführt, wenn sie angesprochen wird – in unserem Fall fünf Mal innerhalb des ForEach-Statements = 25 Ausführungen des darin enthaltenen where-Statements.

Eine simple Lösung des Problems könnte folgendermaßen aussehen:

var myOrderedList = (from x in myEnum orderby x.CustomOrderBy("d") select x).ToArray();

Der Aufruf von .ToArray() wandelt das IEnumerable<string> einmalig (außerhalb des ForEach) in ein echtes Array mit den sortierten Entitäten. Damit muss nicht mehr bei jedem Zugriff die Liste erneut sortiert werden.

Über diese „Feinheiten“ von LINQ sollte man sich im Klaren sein, wenn man LINQ verwendet. Beide Verhaltensweisen (IEnumerable und List) haben Vor- aber auch Nachteile.

Tags: .NET jQuery LINQ

2 Kommentare

13.07.201113:59 Uhr
Gordon Breuer

Hallo 🙂

Im letzten Code-Snippet steht ein .ToArray(), im Satz darunter wird jedoch von .ToList() gesprochen – nur eine Kleinigkeit.

So long and thx for the post,
Gordon

15.07.201118:55 Uhr
Sven Erik Matzen

Hallo.

Ja, habe ich jetzt korrigiert – danke für den Hinweis. Ich hatte zunächst das Beispiel mit einer .ToList() – Arrays sind aber etwas leichtgewichtiger 😉

Viele Grüße,
Sven

Dein Kommentar wartet auf Freischaltung.

Artikel kommentieren

Zurück

Tag Cloud


Kontakt aufnehmen


Anrufen

Gerne beantworten wir Ihre Fragen in einem persönlichen Gespräch!


Kontakt aufnehmen

Schreiben Sie uns eine E-Mail mit Ihren Fragen und Kommentaren!