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.
Hallo,
wozu dient eigentlich der int im Dictionary.TValue?
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.
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.
Rein interessehalber, wie ermittelst du dann in Frage kommende Wörter?
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.
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
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.
Das ist der klassische Fall, wo man Redis verwendet.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code