Announcement

Collapse
No announcement yet.

Wie Daten (Objekte) am performantesten Speichern?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wie Daten (Objekte) am performantesten Speichern?

    Hallo Community, ich habe folgendes Problem:
    Ich arbeite grad an einer Art PIM (Personal Information Manager) zur Verwaltung von Kontakten, Terminen usw.
    Die Daten halte ich als Objekte zur Laufzeit in verschiedenen Listen (als eine Liste für Personen, eine für Termine… um genau zu sein sind es ObservableCollections).

    Meine Erste Frage: ist diese Lösung speicherschonender als z.B. das ganze mit eine DataSet zu lösen?


    Ein weiterer Punkt ist es die Daten persistent abzulegen und beim nächsten Programmstart wieder zu laden.

    Ich habe bereits die Objektlisten als XML serialisiert. Das erscheint mir jedoch relativ langsam (besonders das deserialisiern dauert).

    Die Zweite Frage: wie kann man das performanter und möglichst ressourcenschonend lösen? (Eine Datenbank möchte ich nicht unbedingt verwenden) Wie viel Objekte letzt endlich gespeichert werden müssen, weis ich in meinem falle noch nicht... evtl. um die 100 .. überlegt mal wie es in euren Planern aussieht

    Ich bin für jeden Hinweis dankbar.

    Gruß Jonn

  • #2
    Hallo,

    Dein Vorgehen ist vermutlich speicherschonender als DataSet/DataTable, denn Letzteres bietet mehr Möglichkeiten (Select, Sort, DataView, DataRelations usw.). Das sollte aber die Nutzung durchaus erleichtern, und das Speichern und Neuladen ist mit ReadXml/WriteXml auch problemlos möglich (und ruck-zuck erledigt).

    Also lautet meine Empfehlung eindeutig DataSet mit Xml.

    Jürgen
    Zuletzt editiert von Jürgen Thomas; 17.12.2008, 11:20.

    Comment


    • #3
      Ok danke, das wäre eine Möglichkeit. Ich habe das mal getestet und das Speichern/Laden als XML geht beim DataSet tatsächlich schneller.

      (Solche Sachen wie sortieren habe ich bei meiner Objektliste bis jetzt immer mit einer SortDescription für meiner ListBox erschlagen.)


      Mir drängt sich aber grad nebenbei folgende frage auf:
      Wie würde das den z.B. ein alter C++ Hase lösen, der kein Net Framework mit all seinen wunderbaren Funktionalitäten verwenden will? Wie hat man den größere Datenmengen zur Laufzeit bereitgehalten und persistent abgelegt bevor es DataSets und ähnliches gab…auch in Arrays? (Ich bin fast nur mit Dot. Net groß geworden und kenne nichts anderes)

      Comment


      • #4
        Originally posted by Jonn55 View Post
        Mir drängt sich aber grad nebenbei folgende frage auf:
        Wie würde das den z.B. ein alter C++ Hase lösen, der kein Net Framework mit all seinen wunderbaren Funktionalitäten verwenden will? Wie hat man den größere Datenmengen zur Laufzeit bereitgehalten und persistent abgelegt bevor es DataSets und ähnliches gab…auch in Arrays? (Ich bin fast nur mit Dot. Net groß geworden und kenne nichts anderes)
        Hallo Jonn,

        wenn es in erster Linie um Performance und Speicherbedarf geht, würde ich generische Collections (List<T>, Dictionary<T>) verwenden und darin die Daten halten. Zum Persistieren der Daten empfiehlt es sich für die Datenobjekte das ISerializable Interface zu implementieren und sich um das De-/Serialisieren selbst zu kümmern.

        Bin zwar kein alter C++ sondern alter Pascal Hase, aber für beide gilt: Man verwendet die Collection Objekte, die es mittlerweile in den jeweiligen Libraries gibt oder schreibt sich halt "schnell" selbst was. Und das Persistieren ist eigentlich einfacher als mit DotNet. Mit "altem" Pascal bzw C++ kann man die Daten (da kein Managed Code) direkt aus dem Speicher auf die Platte schreiben.

        Gruß
        Peter

        Comment


        • #5
          Originally posted by Peter Enz View Post
          Hallo Jonn,

          wenn es in erster Linie um Performance und Speicherbedarf geht, würde ich generische Collections (List<T>, Dictionary<T>) verwenden und darin die Daten halten.
          Aua, Generics (besser Generic Collections) in Zusammenhang mit Performance und Speicherbedarf zu nennen ist so nicht richtig. Es sei denn es geht um die Performance des Programmiervorgangs. In aller Regel gibts nix Speicherschonenderes Wie ein (typisiertes) Array. Das dabei allerdings der Aufwand höher ausfällt und somit auch eher die Anzahl von Fehlern zunimmt steht wieder auf einem anderen Blatt.
          Just be DRY and KISS your customers.

          Comment


          • #6
            Originally posted by Frischmilch View Post
            Aua, Generics (besser Generic Collections) in Zusammenhang mit Performance und Speicherbedarf zu nennen ist so nicht richtig. Es sei denn es geht um die Performance des Programmiervorgangs. In aller Regel gibts nix Speicherschonenderes Wie ein (typisiertes) Array. Das dabei allerdings der Aufwand höher ausfällt und somit auch eher die Anzahl von Fehlern zunimmt steht wieder auf einem anderen Blatt.
            Aua, da hat sich einer die Implementation von List<T> noch nicht angeschaut.
            Wenn Du das mal machst, wirst Du feststellen, dass ein List<T> nur ein Wrapper um ein ein T[] ist, plus zwei ints und einem leeren T[]. Und was die Performance angeht, geben sie sich auch nix. Aber wenn Du in einer Struktur, die viele viele KB benötigt, ungefähr 20 Bytes sparen willst, nur zu.

            Gruß
            Peter

            P.S:
            Nochwas vergessen:
            Originally posted by Frischmilch View Post
            Generics (besser Generic Collections)
            ist nicht ganz richtig. Generics treten nicht nur im Zusammenhang mit Collections auf. Zum Beispiel: Generische Methoden etc.
            Zuletzt editiert von Peter Enz; 18.12.2008, 12:35. Reason: Zusatz

            Comment


            • #7
              Danke euch, das war schon mal sehr aufschlussreich und interessant.

              Originally posted by Peter Enz View Post

              ... sich um das De-/Serialisieren selbst zu kümmern.
              Was meinst du damit konkret?

              Comment


              • #8
                Originally posted by Jonn55 View Post
                Was meinst du damit konkret?
                Implementiere für die Objekte, die Du persistieren willst, das ISerializable Interface.

                Ein Beispiel findest Du in der SDK/Doku unter ISerializable Interface oder der ISerializable.GetObjectData Methode. Im Prinzip musst Du zwei Methoden implementieren: ISerializable.GetObjectData und einen speziellen Konstruktor für Deine Klasse

                Code:
                Klasse(SerializationInfo info, StreamingContext context).
                Wie Du Deine Daten dann serialisierst, bleibt völlig Dir überlassen. Du kannst zum Beispiel Deine Objekte in ein Byte-Array packen (siehe Klasse BitConverter) und wenn Du willst, kannst Du das Byte Array sogar noch komprimieren (GZipStream).

                Ich habe damit neulich etwa Faktor >20 gegenüber Standard Xml-Serialisierung einsparen können. Ist sicherlich mehr Arbeit als dem Framework alles zu überlassen, aber wenn Speicher eine Rolle spielt...

                Gruß
                Peter

                Comment


                • #9
                  Originally posted by Peter Enz View Post
                  Aua, da hat sich einer die Implementation von List<T> noch nicht angeschaut.
                  Wenn Du das mal machst, wirst Du feststellen, dass ein List<T> nur ein Wrapper um ein ein T[] ist, plus zwei ints und einem leeren T[]. Und was die Performance angeht, geben sie sich auch nix. Aber wenn Du in einer Struktur, die viele viele KB benötigt, ungefähr 20 Bytes sparen willst, nur zu.
                  Okay du hast gewonnen, man sollte wohl nicht vorschnell von den Template Library Collections auf die .NET Collections schließen.
                  Allerdings: Beim dynamischen Erweitern der Liste ist vorsicht geboten: Die Kapazität der Liste wird verdoppelt und für ein neues Array verwendet, d.h. für das "Ergänzen" von nur einem Wert, kann u.U. sehr viel Speicher verbraten werden, und das kann schon zu einem Engpass führen. Und ganz nebenbei wird noch die Copy() Methode des Arrays aufgrufen. Und das jedesmal wenn man ein Wert anfügt. Komfortabel aber nicht performant.
                  Ich würde also (zumindest dem Namen nach) für sich eine oft ändernde Liste eher zur LinkedList greifen . Aber das war ja nicht das Thema.

                  Originally posted by Peter ENZ View Post
                  ist nicht ganz richtig. Generics treten nicht nur im Zusammenhang mit Collections auf. Zum Beispiel: Generische Methoden etc.
                  Das war Java Jargon, tut mir leid. Dort kenn ich die generischen Collections als "Generics". Ich werds nicht wieder tun.
                  Just be DRY and KISS your customers.

                  Comment


                  • #10
                    Super, vielen Danke euch beiden. Ich werde mich mal um den eigenen Serializer kümmern, muss mich aber darüber noch mal genau belesen.

                    Ich habe inzwischen noch etwas experimentiert und bin dabei auf ein weiters Problem gestoßen. Ich vermute mal, dass ich ein Entwurfsfehler bei meinen Klassen gemacht habe, weis aber nicht so genau wie ich jetzt vorgehe muss.

                    Hier ein Auszug aus meinen Code:

                    [highlight=c#]
                    //Klasse Person
                    // [ Serializable ]
                    public class Person
                    {
                    public string Name { get; set; }
                    public string Forname { get; set; }
                    .....
                    }

                    //Klasse PersonenListe
                    // [ Serializable ]
                    public class PersonList : List<Person>
                    {
                    public PersonList read_PersonList(){...}
                    public void write_personList(){...}
                    }
                    [/highlight]

                    Diese beiden Klassen existiern in dieser Form noch einmal für Termine.
                    Ich habe also 2 Listen verschiedenen Typs ( List<Person> und List<Termin> ).
                    Jetzt habe ich natürlich ein Problem beim Serialisieren dieser beiden Listen in einer Datei.

                    Wie gehe ich hier vor?
                    Zuletzt editiert von Jonn55; 19.12.2008, 12:52.

                    Comment


                    • #11
                      Originally posted by Jonn55 View Post
                      Diese beiden Klassen existiern in dieser Form noch einmal für Termine.
                      Ich habe also 2 Listen verschiedenen Typs ( List<Person> und List<Termin> ).
                      Jetzt habe ich natürlich ein Problem beim Serialisieren dieser beiden Listen in einer Datei.

                      Wie gehe ich hier vor?
                      Du serialisierst in einen Stream (Ist egal ob FileStream, MemoryStream oder was auch immer) und schreibst Deine Klassen hintereinander weg, denn der Formatter schreibt immer an die aktuelle Streamposition.

                      Beispiel:

                      [highlight=c#]
                      using(FileStream fs = new FileStream("DataFile.dat", FileMode.Create))
                      {
                      BinaryFormatter formatter = new BinaryFormatter();
                      try
                      {
                      formatter.Serialize(fs, personen);
                      formatter.Serialize(fs, termine); //Wird hinter die personen geschrieben
                      }
                      catch (SerializationException e)
                      {
                      Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                      throw;
                      }
                      finally
                      {
                      fs.Close();
                      }
                      [/highlight]

                      Lesen geht entsprechend: Stream öffnen und die beiden Objekte nacheinander auslesen.

                      Noch ein Hinweis: Beim Testen macht man gerne mal sowas:

                      [highlight=c#]
                      using(memoryStream stream = new MemoryStream()
                      {
                      BinaryFormatter formatter = new BinaryFormatter();
                      formatter.Serialize(stream, MyObject);
                      MyObjectType readObject = formatter.Deserialize(stream);
                      }
                      [/highlight]

                      und wundert sich, dass das Deserialisieren mit einer SerializationException fehlschlägt. Liegt dann einfach daran, dass die Streamposition am Ende steht.
                      Ein stream.Position=0; vor dem Deserialisieren hilft.

                      HTH
                      Peter

                      Comment


                      • #12
                        Gelöst

                        Genial!
                        So funktioniert es. Peter, ich glaube du besitzt die magische Entwickel- Glaskugel. Das mit der Positionierung war der Knackpunkt.

                        Jetzt läuft alles, danke nochmals auch für die interessanten Einblicke bezüglich Collections.

                        Gruß Jonn

                        Comment

                        Working...
                        X