LINQ-Methode zum Hinzufügen von Elementen zu einem Wörterbuch

8

Ich versuche, etwas mehr über LINQ zu lernen, indem ich Peter Norvigs Rechtschreibkorrektor in C # implementiere.

>

Der erste Teil beinhaltet eine große Wortdatei (etwa 1 Million) und legt sie in ein Wörterbuch, in dem% co_de steht % ist das Wort und key ist die Anzahl der Vorkommen.

Ich würde das normalerweise so machen:

%Vor%

Wo value ein allWords

ist

In LINQ mache ich das momentan so:

%Vor%

Ich vergleiche die 2 Wörterbücher, indem ich mir alle IEnumerable<string> anschaue und sie sind identisch, so dass sie die gleichen Ergebnisse liefern.

Die Schleife <key, value> dauert 3,82 Sekunden und die LINQ-Abfrage dauert 4,49 Sekunden

Ich benutze die Stopwatch-Klasse und fahre im RELEASE-Modus. Ich denke nicht, dass die Leistung schlecht ist. Ich habe mich nur gefragt, ob es einen Grund für den Unterschied gibt.

Mache ich die LINQ-Abfrage auf eine ineffiziente Weise oder fehle ich etwas?

Update: Hier ist das vollständige Benchmark-Codebeispiel:

%Vor%     
Matt Warren 22.01.2010, 16:21
quelle

4 Antworten

5

Einer der Gründe, warum die LINQ-Version langsamer ist, besteht darin, dass anstelle eines Wörterbuchs zwei Wörterbücher erstellt werden:

  1. (intern) von der Gruppe nach Betreiber; Die Gruppe durch speichert auch jedes einzelne Wort. Sie können dies überprüfen, indem Sie ein ToArray () und nicht ein Count () betrachten. Dies ist eine Menge Overhead, die Sie in Ihrem Fall eigentlich nicht brauchen.

  2. Die ToDictionary-Methode ist im Grunde eine Foreach-Abfrage über die eigentliche LINQ-Abfrage, bei der die Ergebnisse der Abfrage einem neuen Wörterbuch hinzugefügt werden. Je nach Anzahl der eindeutigen Wörter kann dies auch etwas dauern.

Ein weiterer Grund dafür, dass die LINQ-Abfrage ein wenig langsamer ist, ist, dass LINQ auf Lambda-Ausdrücken basiert (der Delegat in Dathans Antwort), und das Aufrufen eines Delegaten einen kleinen Mehraufwand im Vergleich zu Inline-Code erfordert.

Bearbeiten: Beachten Sie, dass bei einigen LINQ-Szenarios (wie LINQ to SQL, aber nicht LINQ im Arbeitsspeicher wie hier) das Neuschreiben der Abfrage zu einem optimierten Plan führt:

%Vor%

Beachten Sie jedoch, dass Sie damit kein Wörterbuch erhalten, sondern eine Folge von Wörtern und deren Anzahl. Sie können dies in ein Dictionary mit

umwandeln %Vor%     
Ruben 22.01.2010, 17:01
quelle
1

Wenn ich Ihr zweites Beispiel erstelle und es dann in der Disassembly-Ansicht von Reflector öffne, bekomme ich Folgendes:

%Vor%

Wahrscheinlich dauert es länger, nur weil es mehr Funktionsaufrufe gibt und im Laufe einer Million Iterationen summiert.

    
Dathan 22.01.2010 16:29
quelle
0

Indem ich LINQ komplett missbrauchte, konnte ich erreichen, dass es ungefähr gleich und oft etwas schneller war als die foreach-Schleife, sogar mit einem Delegat-Aufruf:

%Vor%

Selbst wenn foreach so geändert wurde, dass ein ähnlicher Satzausdruck verwendet wurde, wurde es nicht schneller.

    
NetMage 10.05.2017 22:23
quelle
0

Sie können Ihr Problem mit Lambda-Ausdruck lösen:

%Vor%     
Muhammad Masud 10.05.2017 20:46
quelle

Tags und Links