Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Dictionary<string, int> performant deserialisieren/laden
digi333
myCSharp.de - Member



Dabei seit:
Beiträge: 302

Themenstarter:

Dictionary<string, int> performant deserialisieren/laden

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

Hallo,
wozu dient eigentlich der int im Dictionary.TValue?
private Nachricht | Beiträge des Benutzers
chilic
myCSharp.de - Experte



Dabei seit:
Beiträge: 2112

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
digi333
myCSharp.de - Member



Dabei seit:
Beiträge: 302

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
chilic
myCSharp.de - Experte



Dabei seit:
Beiträge: 2112

beantworten | zitieren | melden

Rein interessehalber, wie ermittelst du dann in Frage kommende Wörter?
private Nachricht | Beiträge des Benutzers
digi333
myCSharp.de - Member



Dabei seit:
Beiträge: 302

Themenstarter:

beantworten | zitieren | melden

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
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von digi333 am .
Attachments
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

Du könntest mal schauen ob der UniversalSerializer schneller ist.
private Nachricht | Beiträge des Benutzers
digi333
myCSharp.de - Member



Dabei seit:
Beiträge: 302

Themenstarter:

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
weismat
myCSharp.de - Member



Dabei seit:
Beiträge: 878
Herkunft: Frankfurt am Main

beantworten | zitieren | melden

Ich würde mal Protobuf.NET probieren...
private Nachricht | Beiträge des Benutzers
chilic
myCSharp.de - Experte



Dabei seit:
Beiträge: 2112

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15703
Herkunft: BW

beantworten | zitieren | melden

Das ist der klassische Fall, wo man Redis verwendet.
private Nachricht | Beiträge des Benutzers
jogibear9988
myCSharp.de - Member



Dabei seit:
Beiträge: 586
Herkunft: Offenau

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15703
Herkunft: BW

beantworten | zitieren | melden

Zitat von jogibear9988
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.
private Nachricht | Beiträge des Benutzers