Laden...

Deserialisierung recht langsam

Letzter Beitrag vor 16 Jahren 21 Posts 3.170 Views
Deserialisierung recht langsam

Hallo,

eine Frage zur Serialisierung / Deserialisierung

Ich lese eine Datei mit 75000 Zeilen ein,
verarbeite jede Zeile ( splitten usw ) .
Diese Daten werden dann in einer List<T> gespeichert

Bsp:
eine Zeile : SOPLA 51.277222 11.553056 14 UL620 H NOTGO 51.210833 11.946667 25000 Y SONDU 51.292778 11.461389 25000 N
ist mit Tabs getrennt (\t) wird dann gesplittet und die Daten werden in einer Klasse Wegpunkt gehalten.
Diese einzelnen Wegpunkte werden dann der Liste hinzugefügt :


                    // ICAO
                    icao = split[0];
                    // Lat/Lon
                    lat = (float)Convert.ToDouble(split[1].Replace(".", ","));
                    lon = (float)Convert.ToDouble(split[2].Replace(".", ","));
.
.
Waypoint twp = new Waypoint(icao, airway, airwayHeight, lat, lon);
.
.
_WayPointList.Add(twp);

ich glaube das prinzip sollte klar und Richtig ?? sein.

Das serialisieren dauert laut Teststopuhr 3,6 sekunden.

Zum Deserialisirern brauch ich dann 6,5 Sekunden ca.

Das reine lesen und Speichern der Daten in der Liste, aso ohne serialisieren dauert gerade mal 0.9 Sekunden.

Ist das normal ?

Hier noch das serialiseren und Deserialisieren



        public void SerialisiereListe(List<Waypoint> liste)
        {
            Console.WriteLine("Serialize Liste");
            Stream StreamWrite = File.Create("ListeSaved.bin");
            BinaryFormatter BinaryWrite = new BinaryFormatter();
            BinaryWrite.Serialize(StreamWrite, liste);
            StreamWrite.Close();
        }

        public void DeserialisiereListe()
        {
            Console.WriteLine("DeSerialize Liste");
            Stream StreamRead = File.OpenRead("ListeSaved.bin");
            BinaryFormatter BinaryRead = new BinaryFormatter();
            _WayPointList = (List<Waypoint>) BinaryRead.Deserialize(StreamRead);
            StreamRead.Close();
        }

Vielleicht ist da ja was falsch , was ich jedoch nicht glaube.

Also mach ich was falsch oder ist das normal ?
Kann man das irgendwie beschleunigen ?

Danke und allen ein gesundes neues Jahr noch
Matthias

Das serialisieren dauert laut Teststopuhr 3,6 sekunden.

Zum Deserialisirern brauch ich dann 6,5 Sekunden ca.

Das reine lesen und Speichern der Daten in der Liste, aso ohne serialisieren dauert gerade mal 0.9 Sekunden.

Ist das normal ?

Dass das Deserialisieren doppelt so lange dauert, wie das Serialisieren ist vollkommen normal. Aus folgenden beiden Gruenden:

  1. Speicherreservierung
    Beim Serialisieren sind alle Objekte bereits vorhanden, es muss kein Speicher mehr reserviert werden. Beim Deserialisieren muss fuer jedes Objekt erstmal neuer Speicher reseviert und das Objekt neu angelegt werden.

  2. Splitting / Bekanntheit der Daten
    Waehrend Serialisierung der Serialisierung sind die zu schreibenden Daten bereits bekannt und muessen nur in den Stream "gepumpt werden". Die Deserialisierung ist weitaus komplexer, das dort die eingehenden Strings zerlegt werden und dafuer einige Stringvergleiche bzw. Stringoperationen notwendig sind. Stringoperationen sind grundsaetzlich ziemlich teuer was Rechenzeit angeht.

Kann man das irgendwie beschleunigen ?

Falls die Daten nicht noch von anderer Stelle in genau der Form verarbeitet werden muessen, kann man da meiner Meinung nach noch etwas rausholen, wenn man die Daten binaer anstatt in Textzeilen speichert.

Gruesse,

N1ls

Oder den XmlSerializer verwenden. Der ist deutlich schneller, vor allem wenn vom den vorcompiliert. Die Formatter arbeiten mit Reflection, und das ist bekanntermaßen nicht furchtbar schnell.

Der XmlSerializer kann aber nur mit Properties und Fields umgehen wenn diese public sind. Alles was nicht public ist, läßt er einfach weg.

loop:
btst #6,$bfe001
bne.s loop
rts

Hallo,

ok, ich danke Euch für die Antworten !
Ich werd das mal mit dem XmlSerailizer versuchen.
Das mit dem Binär speichern hab ich nicht ganz verstanden ?
Speichere ich die die daten nicht schon binär wenn ich die serialisiere ?

Danke euch
Matthias

Speichere ich die die daten nicht schon binär wenn ich die serialisiere ?

Hallo,

das kommt eben drauf an welchen Formatter man benutzt. Standardmässig gibts folgende:* SoapFormatter -> Serialisiert in ein Textfile (SOAP Format; lesbar)

  • BinaryFormatter -> Serialisiert in ein Binärfile
  • XmlSerializer -> Serialisiert in ein Textfile (XML Format; lesbar)

Grüsse,
Egon

Hallo,

also denke ich mal das ich daraus schließen kann das der XmlSerialize die schnellste Variante ist oder wie ist das jetzt gemeint ?

Matthias

Dass der XmLSerializer am schnellsten ist, hatte ich ja schon gesagt.

Aus dem erzeugten Format (binär vs. XML) kannst du allerdings nicht auf die Geschwindigkeit schliessen. Ursache für die Performanceunteschiede ist die Art und Weise wie die Daten aus den Objekten gelesen bzw. geschrieben werden.

Der XmlSerializer erzeugt zur Laufzeit Hilfsklassen, die dann ganz "normal" auf die Felder der Objekte zugreifen. Daher auch die Beschränkung auf öffentliche Felder.

Die Formatter hingegegen greifen direkt via Reflection auf die Objekte zu und können so die Zugriffsbeschränkungen (private/protected) umgehen. Das allerdings ist "teuer" und daher deutlich langsamer. Allerdings ist die Performancedifferenz auch von der Größe und der Häufigkeit der Serialisierung abhängig. Man kann sagen: Je größer die Datenmenge, desto mehr macht sich der Geschwindigkeitsvorteil des XmlSerializers bemerkbar. Bei sehr kleinen Menge sind die Formatter vermutlich sogar im Vorteil. Ausnahme: Man kann die Hilfsklassen des XmlSerializers vorcompilieren. Das ist in jedem Falle die schnellste Lösung.

Hallo,

Man kann die Hilfsklassen des XmlSerializers vorcompilieren. Das ist in jedem Falle die schnellste Lösung.

Hmm, also ich bin derzeit auf arbeit und kann hier leider nicht programmieren. Kannst Du mir schon mal nen Hinweis geben wie ich das mache ?

In der Klasse die ich da Serialisiere ist am wichtigsten 2 Listen ( ArrayList [ die ich noch in eine List<T> umwandeln werde ] )
Wenn ich die also auf public setze oder per Property zugreifbar mache müsste das gehen oder ?
Zu der Property gleich mal, das hatte ich glaube ich schon mal.
Um die mitzuspeichern muss ich da set UND get angeben oder reciht get ?

Danke
Matthias

Hallo nochmal,

ich hab grad mal noch ein bischen gelesen.
Scheint nicht so gut zu sein die ArrayList in eine List<T> umzuwandeln weil diese wohl noicht so einfach serialisiert und deserialisiert werden kann oder ?

Matthias

Du musst unterscheiden:

ser.Serialize(myObj, typeof(List<myType>));

geht nicht (geht schon, aber nur mit benutzerdefinierter Serialisierung bei abgeleiteten Klassen). Wenn aber eine List<T> irgendwo in einem Objekt auftaucht, dann wird der Inhalt (!) der Liste korrekt (de-)serialisiert:

ser.Serialize(myList, typeof(MyList));

wobei

public class MyList
{
     public List<Irgendwas> bla;
}

Wenn man eine Liste serialisieren möchte, reicht es also, ein "Dummy-Objekt" drumrum zu ziehen, welches dann die Liste enthält.

Precompilieren:

http://msdn2.microsoft.com/en-us/library/bk3w6240(VS.80).aspx
http://www.cybral.com/downloads.aspx#XmlPrecompiler

Hallo,

so geht es auch:


XmlSerializer xs = new XmlSerializer(liste.GetType());
xs.Serialize(stream,li);

"liste" ist vom Typ List<int>. Dann kann man sich das Dummy sparen.
Oder übersehe ich etwas?

Gruss
tscherno

To understand recursion you must first understand recursion

http://www.ilja-neumann.com
C# Gruppe bei last.fm

Hallo,

so, Flieger is beladen und mal wieder ins Forum geschaut...Danke euch für die Antworten !
Das werd ich nachher nach der Schicht gleich noch testen !!

Das mit dem Precompilieren schau ich mir auch dann an !!
Dank Euch auf jeden Fall !

Matthias

Um die mitzuspeichern muss ich da set UND get angeben oder reciht get ?

public set + get sind beide nötig.

"Listen" müssen mindestens "IEnumerable<T>" implementieren und eine Methode "Add<T>(T item)" haben um als listen erkannt zu werden.

loop:
btst #6,$bfe001
bne.s loop
rts

Hallo,

also das mit dem XmlSerializer stellt sich anscheinend als ganz schön schwierig raus.
Ich könnte jetzt sagen ok, 13 seknden zum starten des programms bei der Datenmenge ist ok, aber dann hät ich ja nix dazugelernt. Ein bischen Ehrgeiz hat man ja auch.

Also erklär ich euch erst mal was ich gemacht habe :

Das ganze hier ist ja ein Pathfinding programm sozusagen.
Also die Hauptklasse ist "Graph". in der sind die beiden Listen LN ( Liste mit Nodes ) und LA( Liste mit Arcs ), beides derzeit immer noch vom Typ ArrayList.
So, die Liste Nodes ( LN ) enthält nun Objekte vom typ "Node". Eine Klasse die die ganzen Wegpunkte enthält.
Die LA enthält dann die ganzen Ecken.
Nachzulesen ist das Design auch hier : http://www.codeproject.com/KB/recipes/graphs_astar.aspx

Nun hab ich erst mal das hier versucht :


        // Graph als XML speichern
        public void GraphToXml(Graph g, string FileName)
        {
            

            XmlSerializer serializer = new XmlSerializer(typeof(Graph));
            TextWriter writer = new StreamWriter(FileName);
            try
            {
                serializer.Serialize(writer, g);
            } catch(Exception e)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(e.Message);
                sb.Append(e.InnerException);
                TextWriter tw = new StreamWriter("error.txt");
                tw.Write(sb);
                tw.Close();
                Console.WriteLine("Message: {0} \nInnerException: {1}",e.Message, e.InnerException);
            }
            writer.Close();
        }

So, hab da jetzt mal nen TW mit reingemacht damit ich die Fehlermeldung leichert kopieren kann:

Beim Generieren des XML-Dokuments ist ein Fehler aufgetreten.System.InvalidOperationException: Der Typ :::

Ich weiß nur nicht so genau was mir das jetzt sagen soll ?

was mach ich denn da falsch ?
Matthias

PS.: ich bin aber gerade dabei die Arraylisten in List<T> umzubauen !!

Das zu serialisierende Objekt (in deinem Code "g") muss einen parameterlosen Konstruktor besitzen. Ist das der Fall?

Gruss
tscherno

To understand recursion you must first understand recursion

http://www.ilja-neumann.com
C# Gruppe bei last.fm

Jap, hab ich ihm verpast !

Mathias

Hallo,

das ist aber nicht alles. Der Serialisierer ist meiner Meinung nach ziemlich dumm. Dem was beizubringen, macht einen wahnsinnig. Es gibt eine Überladung des Konstruktors, welcher du zusätzliche zu erwartende Typen angeben kannst. Wie das sein kann, dass ein Typ unerwartet ist? Keine Ahnung, aber wenn du eine Eigenschaft des Typs Object hast, welche eine Instanz eines Typen, welche eine Instanz eines anderen Typen als Wert hat, kommt das glaube ich vor.

Obwohl hier ja eigentlich alle der Meinung sind, der Formatter sei mist, sehe ich das anders. Im Zusammenspiel mit dem Interface ISerializable ist der Formatter meines Erachtens nach sehr gut.
Volle Kontrolle über de-/serialisieren.
Keine Reflektion und dadurch sehr schnell.

Gruss
Friedel

Ohne Ziel ist auch der Weg egal.

BTW: Graphen mit XmlSerializer kann kritisch werden. Kein Zyklen, keine Normalisierung (will meinen Kopien von Knoten, etc.).

Die Fehlermeldung weisst auf einen Basisklasse mit Subklassen hin. Siehe XmlIncludeAttribute.

Im Zusammenspiel mit dem Interface ISerializable ist der Formatter meines Erachtens nach sehr gut.
Volle Kontrolle über de-/serialisieren.
Keine Reflektion und dadurch sehr schnell.

Aber eine Menge Code für jede beteiligte Klasse. Kein Klingelkram.

Hallo svenson,

Aber eine Menge Code für jede beteiligte Klasse. Kein Klingelkram.

Das stimmt, aber hat man sich an den Mehraufwand gewöhnt, bietet einem die Schnittstelle viele nützliche Eingriffsmöglichkeiten. Nur so als Beispiel: Versionskontrolle verschiedener Versionen des zu (de-)serialisierenden Typs.

Möchte man aber "etwas einfaches" schnell und simple serialisieren ist der XmlSerializer die "bessere" Wahl. Bei komplexen Typen, welche nicht durch einen parameterlosen Konstruktor und getter und setter für alle Eigenschaften verwurschtelt werden sollen, ist ISerializable die Möglichkeit.

Gruss
Friedel

Ohne Ziel ist auch der Weg egal.