hotti: Serialize, Struct in einer Datei ablegen

hi,

s. Thema. Wo kann ich da mal was nachlesen? Also ich hab schon ein paar kleine Vorstellungen darüber, wie ich das mache. Das Struct ist eine Datenstruktur mit key-value. Ich hab mir folgendes ausgeheckt für die Datei:

Header
------
4 byte: Anzahl der Einträge (integer)
4 byte: Position key1
4 byte: Länge key1
4 byte: Position value1
4 byte: Länge value2
usw. Bis hier alles Integer long (32  Bit, 4 byte)

Data
------
variabel, binary

Die Datei soll performant zu lesen sein, o.g. Scheme dürfte dem genügen, mit einer passenden Maske kann ich den Header exact auslesen, dann den Zeiger positionieren und die Daten lesen.

Wer mir über son Zeug maln bissl mehr erzählen kann, sollte jetzt reden (oder für immer schweigen) ;-)

Viele Grüße,
Horst Hasenkiller

--
Toneier verraten sich durch einen charakteristischen Klang, beim Versuch die Eier aufzuschlagen.
  1. Hallo,

    s. Thema. Wo kann ich da mal was nachlesen?

    wo immer du willst ... ;-)

    Ich hab mir folgendes ausgeheckt für die Datei:

    Header

    4 byte: Anzahl der Einträge (integer)
    4 byte: Position key1
    4 byte: Länge key1
    4 byte: Position value1
    4 byte: Länge value2
    usw. Bis hier alles Integer long (32  Bit, 4 byte)

    Data

    variabel, binary

    Dieser Header enthält Redundanzen. Um Position und Länge eines key- oder value-Eintrags zu bekommen, musst du zwei DWORDs lesen. Dann ist es aber unnötig, die Länge mitzuspeichern, denn die ergibt sich aus der Position des gesuchten und des darauffolgenden Eintrags. Wenn die Anzahl der Einträge nicht ins Uferlose wächst, kann man sogar den gesamten Header als DWORD-Array im Arbeitsspeicher halten, was der Performance zugute kommen könnte.
    Insgesamt finde ich den Ansatz recht gut. Er hat zwar einen Nachteil, nämlich dass er nur "flache" Datenstrukturen abbilden kann, keine verzweigten. Wenn man das allerdings möchte, wird's ziemlich aufwendig.

    Wer mir über son Zeug maln bissl mehr erzählen kann, sollte jetzt reden (oder für immer schweigen) ;-)

    Was willste denn hören?

    Fröhliche Eiertage,
     Martin

    --
    Kleine Geschenke erhalten die Freundschaft.
    Große verderben sie aber meist auch nicht.
    1. hi Martin, mein Lieber,

      Dieser Header enthält Redundanzen. Um Position und Länge eines key- oder value-Eintrags zu bekommen, musst du zwei DWORDs lesen. Dann ist es aber unnötig, die Länge mitzuspeichern, denn die ergibt sich aus der Position des gesuchten und des darauffolgenden Eintrags.

      Hmmmm, ich werd nochmal drüber nachdenken... das Positionsgerechne kostet jedoch auch ein bischen CPU...

      Wenn die Anzahl der Einträge nicht ins Uferlose wächst, kann man sogar den gesamten Header als DWORD-Array im Arbeitsspeicher halten, was der Performance zugute kommen könnte.

      Genau!, auf jeden Fall, wird der Header im Speicher gehalten, solange das Programm/Script läuft. Nur der Header. Das wird fein :-)

      Evntl. nehme ich statt 32 Bit nur 16 Bit (Schablone "S" statt "N"), das reicht auch (gibt 65536 Einträge).

      Insgesamt finde ich den Ansatz recht gut.

      Na, ich erst *Grins*

      Er hat zwar einen Nachteil, nämlich dass er nur "flache" Datenstrukturen abbilden kann, keine verzweigten. Wenn man das allerdings möchte, wird's ziemlich aufwendig.

      Im Moment (noch) kein Thema.

      Wer mir über son Zeug maln bissl mehr erzählen kann, sollte jetzt reden (oder für immer schweigen) ;-)

      Was willste denn hören?

      Dein Hinweis "DWORD" ist schonmal goldrichtig, danke!!!

      Fröhliche Eiertage,

      Schokoladeneier sind eine gute Alternative zu Toneiern.

      Viele Grüße auch an Alle,
      Horst Haselhuhn (Legehennen-Experte)

    2. hi Martin,

      Dieser Header enthält Redundanzen. Um Position und Länge eines key- oder value-Eintrags zu bekommen, musst du zwei DWORDs lesen....

      Die Redundanzen sind ok, das vereinfacht sowohl das Schreiben als auch das Lesen einer solchen Datei. Ich habe das gestern soweit fertiggebracht, dass Arrays of Arrays serializiert in Dateien abgespeichert werden können. In Perl sieht das in Etwa so aus:

      ['url', 'descr', 'title', 'lastmod', 'folder'] # ein Objekt (Record)

      Anstelle DWORD ists bei mir ein short, das sind dann nur 2 byte je Integer (16 Bit, ermöglicht 65536 Einträge, reicht dicke). Der Dateiheader sieht so aus (hier mit Zeilenumbruch aufgezeigt, in der Datei selbst sind die Bits hintereinander weggeschrieben):
      2 byte: Anzahl der Einträge
      2 byte: Anzahl der Eigenschaften eines Objekts (lt. o.g. Beispiel 5 Datenfelder)
      Je Eintrag gibt es dann einen header, der geht so:
      2 byte: Position
      2 byte: Länge
      usw., also 4 byte je Datenfeld.

      Die binary steht dann hintendran.

      Zum Lesen der Datei wird nur der Index (header) solange im Speicher gehalten, wie das Script am Leben ist. Aus Performgründen werden die Aufgaben auf verschiedene Funktionen verteilt, je nach Verwendungszweck wird dann entweder nur ein Objekt ausgelesen oder auch mal das komplette Array. Auch zum Lesen des headers (index) gibt es eine extra Funktion, die liest nur den Dateiheader, wie weit diese Funktion lesen muss, steht praktisch in den ersten 4 bytes.

      Derzeit ist ein Record nur per Index [0], [1] usw. adressierbar, auch die Datenfelder. Ich lasse mir noch was einfallen, was eine namentliche Adressierung ermöglicht. Mehr geht im Moment nicht aber das ist schonmal ne ganze Menge ;-)

      viele Grüße,
      Horst Pfeifenraucher

      1. Hallo,

        Dieser Header enthält Redundanzen. Um Position und Länge eines key- oder value-Eintrags zu bekommen, musst du zwei DWORDs lesen....
        Die Redundanzen sind ok, das vereinfacht sowohl das Schreiben als auch das Lesen einer solchen Datei.

        vielleicht, ja, aber damit lassen sich auch prima Konflikte erzeugen. Beispiel:

        Eintrag #0   Offset 0x0000  Länge 0x0010
        Eintrag #1   Offset 0x0010  Länge 0x0030
        Eintrag #2   Offset 0x0040  Länge 0x0020
        Eintrag #3   Offset 0x0050  Länge 0x0010

        Hier belegen Eintrag #2 und Eintrag #3 teilweise denselben Bereich. Okay, auch daraus kann man bei manchen Datenstrukturen einen Nutzen ziehen; man kann Teilmengen eines Eintrags als eigenständige Einträge anlegen, ohne die Daten selbst zu duplizieren. Ist aber heikel ...

        Anstelle DWORD ists bei mir ein short, das sind dann nur 2 byte je Integer (16 Bit, ermöglicht 65536 Einträge, reicht dicke).

        Wirklich? Hast du daran gedacht, dass damit auch die Gesamtlänge der serialisierten Struktur auf 64kB begrenzt ist? Und das ist nicht viel! Okay, wenn man aufpasst, kriegt man mit (64k-1) Offset plus (64k-1) Länge eines Eintrags insgesamt (128k-2) hin. Ist aber auch nicht wirklich üppig.

        Das Konzept ist also noch ausbaufähig bzw. zeigt noch Optimierungspotential. ;-)

        Ciao,
         Martin

        --
        Husten kann böse Folgen haben.
        Besonders im Kleiderschrank.
        1. Ein freudestrahlendes Hai Martin!

          vielleicht, ja, aber damit lassen sich auch prima Konflikte erzeugen. Beispiel:

          Eintrag #0   Offset 0x0000  Länge 0x0010
          Eintrag #1   Offset 0x0010  Länge 0x0030
          Eintrag #2   Offset 0x0040  Länge 0x0020
          Eintrag #3   Offset 0x0050  Länge 0x0010

          Hier belegen Eintrag #2 und Eintrag #3 teilweise denselben Bereich.

          Ja, das sehe ich sofort ;-)
          Ja, ne, is klar, das darf natürlich nicht passieren und mein Perlscript tut in dieser Hinsicht fehlerfrei. Mein "Adressblock" ist konsistent, auch mit den Redundanzen. Letztere verringern ein bischen die CPU beim Lesen der binary Datei, Offset und Length liegen sofort als Pärchen vor, length muss nicht erst berechnet werden.

          Anstelle DWORD ists bei mir ein short, das sind dann nur 2 byte je Integer (16 Bit, ermöglicht 65536 Einträge, reicht dicke).

          Halt Dich fest *G*: Genau das ist mir gestern abend kurz vor dem Einschlafen durch den Hinterkopf geschossen! Freilich, da hast Du vollkommen Recht, das ist praktisch sauknapp für eine lineare Adressierung. Es bleibt also beim DWORD.

          Das Konzept ist also noch ausbaufähig bzw. zeigt noch Optimierungspotential. ;-)

          Es steht!!!!! Jetzt geht die Arbeit erstmal richtig los, to Doooooo:

          • Perl Modul schreiben
          • Evntl. OOP, mal sehen.

          Erster produktiv Einsatz wird mein CMS sein, da ists momentan so, dass zum Request einer URL ein kompletter hash mit ~70 kb in den RAM geladen wird, wobei dazu auf dem Server eine ini-Datei eingelesen wird. Mit der neuen Art, die Objekte in einer bin-Datei, wird zukünftig nur noch der Adressblock aus der Datei in den Speicher geholt und die Attribute dann aus einem FileHandle gelesen, das sind nur noch ein paar byte.

          Das wird fein, Rock & Roll ;-)

          Vielen Dank, schön dass Du mitgelesen hast,
          was Eigenes entwickeln macht immer Spaß,
          viele Grüße an Alle,

          Horst Fröhlisch

          --
          Have a Cigar!
  2. Moin!

    s. Thema. Wo kann ich da mal was nachlesen? Also ich hab schon ein paar kleine Vorstellungen darüber, wie ich das mache. Das Struct ist eine Datenstruktur mit key-value. Ich hab mir folgendes ausgeheckt für die Datei:

    Wieso Datei? Zum entspannten Ablegen von beliebig konstruierten Key-Value-Paaren gibts fertige, performante, robuste und standardisiert ansprechbare existierende Lösungen, z.B. CouchDB.

    Die Datei soll performant zu lesen sein, o.g. Scheme dürfte dem genügen, mit einer passenden Maske kann ich den Header exact auslesen, dann den Zeiger positionieren und die Daten lesen.

    Über das performante Schreiben steht bei dir nix.

    - Sven Rautenberg

    1. Moin Sven,

      Wieso Datei? Zum entspannten Ablegen von beliebig konstruierten Key-Value-Paaren gibts fertige, performante, robuste und standardisiert ansprechbare existierende Lösungen, z.B. CouchDB.

      Brot gibts auch fertig zu kaufen. Trotzdem backe ich seit 20 Jahren mein Brot selber.

      Danke und viele Grüße,
      Horst Baecker ;-)

    2. Moin lieber Sven,

      Wieso Datei? Zum entspannten Ablegen von beliebig konstruierten Key-Value-Paaren gibts fertige, performante, robuste und standardisiert ansprechbare existierende Lösungen, z.B. CouchDB.

      "Apache CouchDB is a document-oriented database..."

      Ich habe auf dem Server eine Datei, in der sind Objekte und Eigenschaften abgelegt, ein Objekt ist ein URL, Eigenschaften sind Last-Modified, Title, Description usw.

      Diese Datei ist derzeit auf Darstellungsebene strukturiert, es ist eine ini-Datei. Die Datei wird jedoch maschinell erzeugt und auch maschinell gelesen, es ist deswegen nicht notwendig, die Strukturierung auf dem Presentation Layer zu machen (das wäre sinnvoll, wenn ich diese Datei in den Editor nehmen müsste, was jedoch nicht so ist).

      Mein erklärtes Ziel ist es daher, die Objekte so abzulegen, dass die Attribute direkt und performant adressierbar sind, sprich: auf Bitebene. Das ist der Hintergrund.

      Viele Grüße,
      Horst Butterberg

  3. hi,

    s. Thema. Wo kann ich da mal was nachlesen?

    So, Leute ;-)

    Mittlerweile ist das Zeugs gereift und ausgegärt. Hab nun selbst was zum Nachlesen geschrieben:

    http://rolfrost.de/binfile.html

    Wo ich schon seit Wochen dran bin, mehr oder weniger hartnäckig. Freilich gibt es da auch noch das Perl-Modul Storable.pm, aber das ist für meine Zwecke ein bischen zu RAM-Intensiv und auch die Datei enthält zu viele Redundanzen(*). Die Idee, für eine Speicherung von Daten diese einfach nur zu serialisieren, die logische Struktur hingegen softmäßig draufzusetzen, finde ich am Besten.

    (*) Bei einer Sammlung von Objekten stehen in der Datei jedesmal die Namen der Attribute, das ist mir zu aufgequollen. Da kann ich ja gleich einen Dump machen und mit eval wieder einlesen, da brauche ich keine Low Level Strukturierung.

    Viele Grüße,
    Horst Glucke

    1. Mittlerweile ist das Zeugs gereift und ausgegärt. Hab nun selbst was zum Nachlesen geschrieben:

      http://rolfrost.de/binfile.html

      Das klingt als ob du DB_File gesucht hättest?

      Soweit ich das in Errinnerung habe, liest dB_File nicht alles komplett ein, wenn es nicht nötig ist und organisiert ebenfalls die Daten kompakt und ist recht schnell. Kannste ja mal vergleichen mit deinem Weg.

      Struppi.