Laden...

Dictionary<string, int> performant deserialisieren/laden

Erstellt von digi333 vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.320 Views
D
digi333 Themenstarter:in
290 Beiträge seit 2006
vor 9 Jahren
Dictionary<string, int> performant deserialisieren/laden

Ich schreibe gerade einen Spell-Checker (Rechtschreibprüfung) aus wissenschaftlichen Gründen (besitzt besonders viele Alternative Namen von Städten). Das Programm funktioniert auch wie erwartet sehr gut, aber beim Programm-Start wird das Wörterbuch als Dictionary<string, int> geladen. Leider dauert das jedoch sehr lang und daher meine Frage... kennt ihr eine schnellere Möglichkeit dieses Wörterbuch als Dictionary zu deserialisieren?


           Dictionary<string, int> dict_words = null;
          ....

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

            if (DWORDS == null)
            {
                BinaryFormatter inF = new BinaryFormatter();
                using (FileStream fs = new FileStream("spellchecker.dat", FileMode.Open))
                {
                    DWORDS = (Dictionary<string, int>)inF.Deserialize(fs);
                }
            }
            stopwatch.Stop();
            System.Diagnostics.Debug.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
            System.Diagnostics.Debug.WriteLine("Dictionary Count: {0}", DWORDS.Count());

Ausgabe:
Time elapsed: 00:09:02.9263397
Dictionary Count: 5131062

PS.: Ich würde auch zu eigenen Tests die Datei zur Verfügung stellen.

W
955 Beiträge seit 2010
vor 9 Jahren

Hallo,
wozu dient eigentlich der int im Dictionary.TValue?

C
2.121 Beiträge seit 2010
vor 9 Jahren

Du kriegst immerhin fast 10.000 Einträge pro Sekunde deserialisiert. Werte lesen, Hash bilden, eintragen... ganz schlecht würd ich das jetzt nicht nennen.

Ich würde anfangen zu testen, ausprobieren.
Lade das erst in einen MemoryStream und lass es von dem Deserialisieren. Unterschied in der Zeit?

Pack die Inhalte in eine Liste von Objekten mit String und int Feld. Dann miss die Zeit wie lange das braucht um es in ein Dictionary einzutragen und vergleiche die mit deiner jetzigen. Dann zeigt sich wie lange das entpacken der einzelnen Datensätze braucht.

Versuche ein anderes Datenformat. Sind es nur immer String und Zahl? String ohne Zeilenumbruch? Bau dir ein eigenes Format z.B. 1234|abHierText.... \n und versuche ob das signifikant schneller geht.

D
digi333 Themenstarter:in
290 Beiträge seit 2006
vor 9 Jahren

Das ist die Wahrscheinlichkeit (Häufigkeit) jedes Wortes. Wenn mehrere Kandidaten zur Korrektur zur Verfügung stehen, nehme das Wort mit der größten Wahrscheinlichkeit.

C
2.121 Beiträge seit 2010
vor 9 Jahren

Rein interessehalber, wie ermittelst du dann in Frage kommende Wörter?

D
digi333 Themenstarter:in
290 Beiträge seit 2006
vor 9 Jahren

Mit der Levenshtein-Distanz... welche angibt wie viele Schreiboperationen man benötigt um ein Wort in ein anderes Wort aus der Datenbank (DWORDS) zu ändern.

Levenshtein-Distanz

W
955 Beiträge seit 2010
vor 9 Jahren

Du könntest mal schauen ob der UniversalSerializer schneller ist.

D
digi333 Themenstarter:in
290 Beiträge seit 2006
vor 9 Jahren

Wow! Genau das habe ich gesucht... ein hoch auf witte (werde dich in meine Nachtgebete einschließen). 😃

Time elapsed: 00:00:06.2798098
Dictionary Count: 5131062

W
872 Beiträge seit 2005
vor 9 Jahren

Ich würde mal Protobuf.NET probieren...

C
2.121 Beiträge seit 2010
vor 9 Jahren

Oder selber machen. Ich tippe mein Beispiel reicht schon als Datenstruktur. Das dann zeilenweise in eine Datei und schon hat man sich allen für diesen Fall überflüssigen Overhead gespart.

Ich würde übrigens außerdem messen wie lange das einfügen blockweise dauert, also die ersten 10.000 Einträge, die zweiten usw. Könnte mir vorstellen dass es mit zunehmender Größe des Dictionary langsamer wird, weil dann immer mehr umgeschichtet werden muss.
Das wäre auch noch ein Versuch, die Anfangskapazität des Dictionary auf einen Wert größer der Anzahl Einträge zu setzen.

16.807 Beiträge seit 2008
vor 9 Jahren

Das ist der klassische Fall, wo man Redis verwendet.

J
641 Beiträge seit 2007
vor 9 Jahren

Hier werden die verschiedensten serializer verglichen:

Binary and JSON serializer benchmarks updated

Oder statts des dictionarys eine sqllite datenbank benutzen...

How do I use a Levenshtein distance function in a sqlite where clause?

cSharp Projekte : https://github.com/jogibear9988

16.807 Beiträge seit 2008
vor 9 Jahren

Oder statts des dictionarys eine sqllite datenbank benutzen...

Ich hatte noch gehofft, dass das niemand empfiehlt, da genau solche Anforderungen nix für eine relationale DB ist, sondern eben dafür memcacheDb bzw Redis (bietet im Vergleich deutlich bessere Leistung und Ergebnisse) geschaffen wurde.

Redis bietet für so einfache Konstrukte (Hashes, Strings, Objekte und Key-Value-Pairs) absolute führende Performance-Werte und dank ServiceStack.Redis einen exzellenten C# Driver.
Zusätzlich ist Redis als einziges seiner Art komplett in Azure verfügbar.

Optimieren kann man das ganze dann noch, wenn ServiceStack.Redis nur zum Lesen (raw) verwendet und den deutlich schnelleren ProtoBuf für das Serialisieren.