Laden...

Serialisierung großer Datenmengen (Binär)

Erstellt von backspeck42 vor einem Jahr Letzter Beitrag vor einem Jahr 921 Views
B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr
Serialisierung großer Datenmengen (Binär)

Hallo,

ich möchte eine große Menge von Daten Binär serializiern. Was würdet ihr vorschlagen. In meinen Datenklassen habe ich ISerializable implementiert. Ich habe bis jetzt eine funktionierende Lösung mit BinaryFormatter - die Serialisierung funktioniert schnell und die erzeugen Dateien sind relativ klein. Auch sehr große Datenmengen sind kein Problem. Allerdings ist BinaryFormatter ja unsicher und soll nicht mehr genutzt werden und das Format ist eine ziemliche Blackbox.
Dann habe ich BSON probiert (Newtonsoft.BSON) - funktioniert im Prinzip auch - ABER: der Newtonsoft Serializer baut das komplette Dokument im Ram zusammen (auch wenn ich die Low-Level-Methoden nutze wie BSonDataWriter.WriteValue() und nicht das Objekt komplett srialisiere). Dadurch funktioniert es zwar bei sehr kleinen Daten gut, bei großen Datenmengen läuft hingegen einfach nur der Speicher voll. Zumindest Newtonsoft.BSON ist damit für mich unbrauchbar.
Daher meine Frage: hat jemand einen Tipp, was man sonst noch nehmen könnte (außer komplett manuelle sertialisierung mittels BinaryWriter)?

Danke schon mal im Voraus,
LG..BS

T
2.219 Beiträge seit 2008
vor einem Jahr

Für sowas würde ich, wenn es binär sein muss, auf Protobuf setzen.
Der .NET BinaryFormatter war in der Vergangenheit nicht das Optimum.

Doku:
https://developers.google.com/protocol-buffers/docs/csharptutorial

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Für sowas würde ich, wenn es binär sein muss, auf Protobuf setzen.

Ok danke. Ja das bin ich auch schon drüber gestolpert - war mir eigentlich zu viel Overhead. Mir wäre eigentlich eine Lösung wie Newtonsoft.BSON ganz lieb, welche einfach die ISerializable Schnittstelle nutzt ...

T
2.219 Beiträge seit 2008
vor einem Jahr

Das Problem bei Bson ist, dass dort z.B. die Feldnamen vollständig mit serialisiert werden müssen.
Dadurch hast du auch einen Overhead, der vermutlich größer sein dürfte.

Bson:
BSON

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor einem Jahr

"Große Datenmengen" ist immer relativ.
Für den einen sind 10MB viel, für den anderen 100GB und die andere lacht immer noch bei 10 Terabyte.

Binärserialisierung heisst i.d.R. immer, dass sich alles exakt standardisiert sein muss.
Bson Serializer gibts viele, musst ja nicht auf Newtonsoft setzen.

6.911 Beiträge seit 2009
vor einem Jahr

Hallo backspeck42,

beschreib noch ein paar der Anforderungen, wie* nur für Verwendung in deinen Anwendungen od. allgemeine Verwendbarkeit

  • schnell serialisieren od. möglichst wenig Speicherbedarf
  • welche Typen (Werttypen, Klassen, Listen, Vererbung) sollen serialisiert werden
  • gibt es ein Schema für die Typen od. eher schemalos
  • etc.

Anhand solcher Kriterien lassen sich dann Technologien wählen bzw. Vorschläge unterbreiten.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Das Problem bei Bson ist, dass dort z.B. die Feldnamen vollständig mit serialisiert werden müssen.
Dadurch hast du auch einen Overhead, der vermutlich größer sein dürfte.

Das ist mir klar. Ich vergebe daher auch sehr kurze Feldnamen (1 - 2 Buchstaben) - das ist kein Problem da ich ISerializable implementiert habe - danke für den Hinweis dennoch!

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

"Große Datenmengen" ist immer relativ.

Es geht um eine Liste von mehreren Millionen Objekten. In meinen Testdaten war die Dateigröße (mit Binaryformatter) bei dieser Menge ca. 1 GB. Das ist aber nicht das Ende der Fahnenstange - es könnte sich durchaus noch verzehnfachen (realistisch gesehen). Daher möchte ich binär serialisieren. JSON hatte ich probiert, das war mir etwas zu Groß dann. (ungefähr das 3 Fache wie mit BinaryFormatter.)

Binärserialisierung heisst i.d.R. immer, dass sich alles exakt standardisiert sein muss.
Bson Serializer gibts viele, musst ja nicht auf Newtonsoft setzen.

Das ist mir bekannt, dass das zusätzliche Probleme bringt - daher wäre es schön, eine Library zu haben, die keine komplette Blackbox ist und ISerializable nutzt. Vermutlich zu viel verlangt..

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

beschreib noch ein paar der Anforderungen

Guter Punkt - vlt. hätte ich das gleich mehr Konkretisieren sollen.

Es geht darum, eine (große) Collection eigener Objekte (die ISErializable implementieren) zu serialisieren. Es geht um einige Millionen dieser Objekte - mit BinaryFormatter komme ich damit auf Dateigrößen von ca. 1GB. Sollte aber auch die 10-Fache menge schaffen können!
Die Daten werden lokal geschrieben, um sie später wiederverwenden zu können (der Algo der die Daten generiert läuft recht lange).
Speicherplatz geht vor performance - es sollte natüclich auch nicht unendlich langsam sein. Mit der Performance wie sie der BinaryFormatter liefert, wäre ich durchaus zufrieden!

T
2.219 Beiträge seit 2008
vor einem Jahr

Aus deinen Kommentaren ist leider nicht ersichtlich, was für Daten du nun speichern willst.
Wenn wir von Millionen von Objekten in einer Collection reden, ist ggf. der Ansatz schon falsch.

Je nachdem was du für Daten hast, kannst du ggf. mit einer NoSQL Datenbank besser fahren als mit einer Custom Lösung.
Ggf. könnte man eine einfache Dokumenten Datenbank mit Json/Bson als Format verwenden.
Oder ggf. auch die Daten in einem Key/Value Store wegspeichern.
Ein paar mehr Details und ggf. ein Beispiel oder Code wären für eine bessere Überlegung nicht verkehrt.

Ebenfalls sei darauf hingewiesen, dass der BinaryFormatter z.B. kein Freund von Änderungen an den Daten ist.
Dieser braucht strikt die gleiche Klassen Instanz beim Deserialisieren wie beim serialisieren verwendet wurde.
Ändert sich die Klasse, sind deine Daten nicht mehr lesbar.
Kann man dann nur über Versionierung der Klassen lösen.

Hier solltest du die nächst beste Lösung nehmen.

Anbei der Hinweis aus der Doku:

BinaryFormatter serialization is obsolete and should not be used. See
>
for more information.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

D
152 Beiträge seit 2013
vor einem Jahr

Bei der Menge wird es aber schon schwierig diese komplett im Speicher (Liste) zuhalten.

Was sind das den für Objekte?
Ggf. würde sich auch eine relationale Datenbank, wie SQLite an bieten.

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Aus deinen Kommentaren ist leider nicht ersichtlich, was für Daten du nun speichern willst.
Wenn wir von Millionen von Objekten in einer Collection reden, ist ggf. der Ansatz schon falsch.

Wie kommst du darauf? Ich analysiere Daten (in dem Falle einen Graph), die Laufzeit dieser Analyse ist recht lang und es fällt eine Collection mit sehr vielen Objekten an - was sollte man in so einem Fall deiner Meinung nach tun? 😉

Je nachdem was du für Daten hast, kannst du ggf. mit einer NoSQL Datenbank besser fahren als mit einer Custom Lösung.
Ggf. könnte man eine einfache Dokumenten Datenbank mit Json/Bson als Format verwenden.
Oder ggf. auch die Daten in einem Key/Value Store wegspeichern.
Ein paar mehr Details und ggf. ein Beispiel oder Code wären für eine bessere Überlegung nicht verkehrt.

Eigentlich brauch ich keinen Key/Value Store. Es handelt sich um eine Collection der selben Klasse - die will ich einfach nur sequenziell wegspeichern! 😉
JSON ist mir zu groß - BSON würde gehen ... aber der Newtonsoft BsonDataWriter baut halt das gesamte Dokument noch mal im Speicher zusammen vorm wegschreiben - daher ist die Lösung für mich in diesem Falle unbrauchbar. Mit kleinen Collections funktioniert BSON aber eigentlich recht gut und auch die Größe der Ausgabedaten ist zufriedenstellend.

Ebenfalls sei darauf hingewiesen, dass der BinaryFormatter z.B. kein Freund von Änderungen an den Daten ist.
Dieser braucht strikt die gleiche Klassen Instanz beim Deserialisieren wie beim serialisieren verwendet wurde.
Ändert sich die Klasse, sind deine Daten nicht mehr lesbar.
Kann man dann nur über Versionierung der Klassen lösen.

Jein - wie ich schrieb, habe ich ISerializable implementiert und somit die Kontrolle, welche Felder serialisiert werden. Im Prinzip könnte man mit dieser Vorgehensweise auch eine Versionierung implementieren (obleich das mit der Zeit vermutlich hässliche werden würde - schon vor Version 12) ... 😉

Hier solltest du die nächst beste Lösung nehmen.

Ja ... und um diese geht es ja ... daher mein Post! 😉

Und das BinaryFormatter obsolte ist und unsicher schrieb ich doch schon im Eingangspost - daher will ich ja davon weg (im Prinzip funktioniert die Lösung für meine Zwecke) ...

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Bei der Menge wird es aber schon schwierig diese komplett im Speicher (Liste) zuhalten.

Was sind das den für Objekte?
Ggf. würde sich auch eine relationale Datenbank, wie SQLite an bieten.

Ja das ist es. Am Ende kann ich aber auch jedes generierte Objekt direkt in den Stream schicken, ohne es zwischendurch im Speicher zu halten.

Es sind recht kleine Objekte die entstehen, wenn ich einen Grpah analysiere - dafür recht viele. Relaionale DB ist halt quatsch, weil es immer die selbe Klasse ist, eben nur sehr viele Instanzen, die entstehen udn gespeichert werden wollen (sequenziell) ...

16.806 Beiträge seit 2008
vor einem Jahr

Wie kommst du darauf? Ich analysiere Daten (in dem Falle einen Graph), die Laufzeit dieser Analyse ist recht lang und es fällt eine Collection mit sehr vielen Objekten an - was sollte man in so einem Fall deiner Meinung nach tun? 😉

Du sprichst halt sehr pauschal. Wir verstehen unter Deiner pauschalen Ausdrucksweise einfach vielleicht was ganz anderes, als Du vor Dir hast. Es kommt im Endeffekt auch viel auf die Programmierung an, was Speicherplatz und damit RAM kostet (zB Datentypen, Class vs Struct etc...).
Ohne also zu wissen, was Du vor Dir hast, können wir halt nur Spekulieren und Allgemein antworten. Da hat er schon nicht unrecht.

Im anderen Thread war das auch schon ein Problem, dass Du nich eine Zeile Code gezeigt hast, was Du da eigentlich machst.
Gerade bei Allocations kann man sehr viel falsch machen - sieht es aber gar nicht, weil man nicht versteht, was unter der Haube passiert (was auch nicht unbedingt Alltagswissen ist).
Wo wir wieder wären: "kleine Objekte" - darunter kann man viel verstehen. Zeig Code!

Jein - wie ich schrieb, habe ich ISerializable implementiert und somit die Kontrolle, welche Felder serialisiert werden.

Kann man machen, ist aber nicht die Hauptaufgabe von ISerializable. ISerializable sagt aus, dass grundlegend eine andere Serialisierung verwendet werden soll, als der Standard.
Eigenschaften ignorieren geht auch einfach mit IgnoreDataMember/NonSerialized.

Dein Problem ist eigentlich nicht das Serialisieren, sondern dass alles im RAM erfolgt. Es gibt genug asynchrone Binary Writer Implementierungen für .NET auf GitHub.
Die Fragen von gfoidl stehen aber immer noch im Raum. Ob das am Ende aber der richtige Weg ist, dass kann Dir hier keiner sagen, weil einfach Infos fehlen.

Relaionale DB ist halt quatsch, weil es immer die selbe Klasse ist, eben nur sehr viele Instanzen, die entstehen udn gespeichert werden wollen (sequenziell)

Hum... das ist eigentlich die Aufgabe von relationalen Datenbanken....
Aber man kann neben Sqlite auch einfach LiteDB dafür nutzen (Schemalos, ganze Objekte, super performant..).

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Du sprichst halt sehr pauschal. Wir verstehen unter Deiner pauschalen Ausdrucksweise einfach vielleicht was ganz anderes, als Du vor Dir hast. Es kommt im Endeffekt auch viel auf die Programmierung an, was Speicherplatz und damit RAM kostet (zB Datentypen, Class vs Struct etc...).

Ich will einzig und allein eine große Menge gleichartiger Objekt squenziell wegspeichern. ICh brauche kein Key/Value-Store, da es sich um gleichartige Objekte handelt. Es ist letztlich eine hirachie aus einigen Objekten - es würde zu weit gehen, das hier zu posten und wäre nutzlos. Es geht darum, die Menge zu handeln. Wie gesagt - meine Lösung funktioniert ja - aber eben (momentan) nur mit BinaryFormatter - Newtonsoft.BSON müllt mir den kompletten Ram zu, da es das komplettte Dokument in selbigen, vor dem wegschreiben, zumsammenbastelt (kann im im Code auch sehen).
Man kann den Test auch einfach mit einer sehr großen List<int> machen - da kann man es sehr schön sehen .. BinanryFormatter schreibt die schnell und ohne großartigen Speicherverbrauch weg - Newton.BSON kommt ab einer bestimmten Größe einfach nicht mehr klar. Darum geht es mir!

Kann man machen, ist aber nicht die Hauptaufgabe von ISerializable. ISerializable sagt aus, dass grundlegend eine andere Serialisierung verwendet werden soll, als der Standard.
Eigenschaften ignorieren geht auch einfach mit IgnoreDataMember/NonSerialized.

Ja das stimmt. Mit ISerializable hat man aber mehr Kontrolle. Außerdem waren Objekte von Drittanbietern involviert - wo ich nicht die entsprechenden Attribute zufügen kann - daher dieser (im Prinzip funktionierende) Ansatz... 😉

Dein Problem ist eigentlich nicht das Serialisieren, sondern dass alles im RAM erfolgt. Es gibt genug asynchrone Binary Writer Implementierungen für .NET auf GitHub.
Die Fragen von gfoidl stehen aber immer noch im Raum. Ob das am Ende aber der richtige Weg ist, dass kann Dir hier keiner sagen, weil einfach Infos fehlen.

Jein - ich halte erstmal die List mit den zu serialisierenden Objekten im Ram - korrekt. Diese belegt dann in meinem Falle 3 GB oder so. Mit dem BinaryFormatter kann ich die problemsol wegschreiben (und nachher wieder laden) - aber mit BSON (Newtonsoft impl.) funktioniert das leider nicht, da dann im Ram noch mal das komplette Dokument zusammengebaut wird (und die bereits große Liste noch mal kopiert).
Die nächste Optimierung wäre, nicht in einer Liste zwischenzuspeichern, sondern gleich an den Stream zu schicken. Würde mir im Falle von Newtonsoft.BSON nichts nützen (Erklärung oben)!

Es gibt genug asynchrone Binary Writer Implementierungen für .NET auf GitHub.

Ja stimmt und alle haben irgendwelche Custom Attirbutes - die ich wiederum in die zu serialisierenden Drittklassen nicht einfügen kann. Dann müsste ich mit Surrogates arbeiten und das möchte ich möglichst vermeiden! 😉

Hum... das ist eigentlich die Aufgabe von relationalen Datenbanken....
Aber man kann neben Sqlite auch einfach LiteDB dafür nutzen (Schemalos, ganze Objekte, super performant..).

Datenbanken bieten noch viel mehr, wie Indizierung z.B. - aber im Prinzip hast du ja Recht in dem Punkt. Wenn ich jetzt aber z.B. nur eine lange Liste mit Doubles oder gleichen Objekten (ohne Key/Value) speichern will, wäre es meiner Ansicht nach übertrieben. Ich wüsste ja z.B. wo Element 40402393 steht im Stream und könnte sofort dahinspringen wenn ich wöllte... 😉

T
2.219 Beiträge seit 2008
vor einem Jahr

Irgendwie drehen wir uns hier im Kreis.
Reden wir nun von komplexen Datentypen wie Klassen oder um grundlegende Datentypen wie int/double?
Bisher lesen sich deine Antworten nicht umbedingt klar und eindeutig.
Dadurch ist eine richtige Lösung nicht wirklich lieferbar.

Da du mit einer Liste im Speicher arbeitest, kannst du die Daten eigentlich auch ohne Probleme in einer Sqlite DB speichern.
Mit einem fertigen OR Mapper wie EF Core wäre der Aufwand dann auch recht gering.
Die Daten einladen ist dann auch kein Kunststück.
Aber ohne die Klasse zu kennen, die du wegspeichern willst, ist das für uns alles nur raten und wir können dir keine Hilfe leisten.

Nachtrag:
Anbei klingt die Klasse, die du speichern willst, auch irgendwie wie nach unsauberen Code.
Wenn du bestimmte Daten wegen einer externen Klasse ausblenden musst, würde ich schon für die Serialisierung eine eigene Klasse anlegen.
Diese sollte auch nur die Daten enthalten, die du speichern/laden willst.
Den Rest kannst du dann einfach auf die eigentliche Klasse mappen z.B. mit AutoMapper.

Nachtrag 2:
Ebenfalls solltest du bei der Menge an Einträgen dir mal das Fliegengewicht Muster anschauen.
Ggf. löst dies auch dein Problem mit der Speichermenge.
Hängt aber davon ab ob du die Zustände der Einträge ohne Probleme/Aufwand auf das Muster anwenden kann.

Fliegengewicht (Entwurfsmuster)

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Reden wir nun von komplexen Datentypen wie Klassen oder um grundlegende Datentypen wie int/double?
Bisher lesen sich deine Antworten nicht umbedingt klar und eindeutig.
Dadurch ist eine richtige Lösung nicht wirklich lieferbar.

Es handelt sich um komplexe Typen. Eine Klasse, welche weitere Klassen enthält, welche wiederum irgendwan aus primitiven Typen besteht. Das ist aber für das Problem (vollaufender Speicher) das ich habe unerheblich - das kann man auch mit einer großen List von int veranschaulichen - daher die Konfusion vermutlich.

Da du mit einer Liste im Speicher arbeitest, kannst du die Daten eigentlich auch ohne Probleme in einer Sqlite DB speichern.
Mit einem fertigen OR Mapper wie EF Core wäre der Aufwand dann auch recht gering.
Die Daten einladen ist dann auch kein Kunststück.
Aber ohne die Klasse zu kennen, die du wegspeichern willst, ist das für uns alles nur raten und wir können dir keine Hilfe leisten.

Mir ist klar, dass es unendlich viele Möglichkeiten gibt ... das ist ja Teil des Problems. Am liebsten wäre mir eine einfache Serialisierung, die ISerializable nutzt (so wie Newtonsoft.BSON oder eben der BinaryFormatter - was ich ja bereits entsprechend implementiert habe, vlt. aber auch nicht der beste Ansatz ist, zugegeben - aber letztlich handelt es sich erstmal noch um einen Prototyp...daher möchte ich den Refactoringaufwand mögichst gering halten).

Wenn du bestimmte Daten wegen einer externen Klasse ausblenden musst, würde ich schon für die Serialisierung eine eigene Klasse anlegen.
Diese sollte auch nur die Daten enthalten, die du speichern/laden willst.

Da hast du Recht - eshalndelt sich zwar bei diesen Drittanbieter-Klassen auch nur um "kleine" Datenklassen" - das wäre die sauberste Lösung und auch die, wo die Reise am Ende evtl. hingehen soll. Vorerst wäre es mir lieb, wenn ich etwas hätte, was ISerializable nutzt - ohne die Unzulänglichkeiten die BinaryFormatter bzw. in meinem Falle Netonsoft.BSON mit sich bringen.

Mal eine Frage aus Softwaretechnischer Sicht: Ist die Nutzung von ISerializable dann überhautp noch sinnvoll, wenn ich letztlich sowieso Surrogates habe, die ich für die Serializierung nutze oder ist es letztlich an sich schon eher ein Antipattern und man sollte es eher nicht nutzen?

16.806 Beiträge seit 2008
vor einem Jahr

Es handelt sich um komplexe Typen. Eine Klasse, welche weitere Klassen enthält, welche wiederum irgendwan aus primitiven Typen besteht. Das ist aber für das Problem (vollaufender Speicher) das ich habe unerheblich -

Genau das ist es nicht: unerheblich. Wir fragen das ja nicht zum Spaß an der Sache.
Komplexe Typen kann man total effizient umsetzen, aber auch total beschissen - und ist für das Problem relevant. Aber Du wehrst Dich mit Händen und Füßen Inhalte zu zeigen. Wie soll man Dir da helfen?
Wenn Du es nicht sagen kannst (weil unbekannt), dann gib wenigstens die Infos dazu. Aber lass doch die Leute nicht an der Glaskugel reiben.
Musst schon mitarbeiten. Les Dir Deine eigenen Beiträge mal aus unserer Sicht durch und frag Dich, ob Du das verstehst 😉

Die Eierlegende Wollmilchsau wirst nicht finden.

Ist die Nutzung von ISerializable dann überhautp noch sinnvoll, wenn ich letztlich sowieso Surrogates habe, die ich für die Serializierung nutze oder ist es letztlich an sich schon eher ein Antipattern und man sollte es eher nicht nutzen?

ISerializable hat halt einen anderen Zweck, bestimmte Use Cases. Habs ja oben schon genannt. Kannst ja problemlos auch ohne ISerializable serialisieren.
ISerializable heisst ja nur, dass Du eine manuelle Logik hast - nicht mehr, nicht weniger.

T
2.219 Beiträge seit 2008
vor einem Jahr

Und zusätzlich kann man mit allen möglichen Ansätzen den RAM voll laufen lassen.
Un abhängig ob wir von List<byte> oder anderen Strukturen reden.

ISerializable habe ich in gut 15 Jahren vielleicht ein oder zwei mal verwenden oder nutzen müssen.
In der Regel kann man mit dem Serializable Attibute und einer ordentlichen Klasse nur für Serialisierung den Standard Fall herstellen.
Deshalb hatte ich dir auch empfohlen eine eigene Klasse ohne den Overhead von Third Party Code umzusetzen.
Ggf. verwalten diese auch nochmal intern eigene Zustände (Member) und erzeugen damit noch einen extra Overhead.

Je nachdem kannst du also noch Daten einsparen sowohl bei der Serialisierung bzw. Persistierung sowie bei der eigentlichen Datenhaltung im Speicher.
Ebenfalls kann man häufig durch Anpassung der Datentypen noch Speichernutzung vermindern.
Aber wie schon mehrmals gesagt müssten wir die genutzten Klassen kennen.

Auch insgesamt musst du mal aus deiner Denkweise rauskommen.
Aktuell hast du dich in ISerializable verbissen, weshalb schon viele weitere Ansätze komplett ausgeschlossen werden.
Dadurch nimmst du dir aber gerade mögliche Optionen, was dich selbst in deinen Möglichkeiten unnötig einschränkt.
Kannst du mit einer eigenen Klasse alles lösen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

6.911 Beiträge seit 2009
vor einem Jahr

Hallo backspeck42,

ich kann "Newtonsoft.BSON" und "BinaryFormatter" schon gar nicht mehr lesen -- das steht in jedem deiner Beiträge 😉

Hilf dir selbst und geh doch bitte auf die Fragen, welche die gestellt werden ein. Auch das würde schon öfters nahegelegt.
Seit Gestern ist als neue Info eigentlich nur "komplexe Typen, Problem auch mit List<int> zeigbar" hinzugekommen. Dafür ist dieser Thread schon recht lange geworden.

Da ich eine List<int> nicht als komplex bezeichnen würde, werden die konrkreten Typen wohl anders ausschauen, nur wie?
Danach richtet sich doch gerade die Serialisierung. Gibts Zyklen, sind die Typen immer gleich, etc. sind da Fragen zu denen du die Antwort liefern solltest bevor jemand danach fragen muss -- schließlich willst ja auch du die Hilfe haben.

"Ein Bild sagt mehr als tausend Worte" ist so ein Spruch der Berechtigung hat. Übertragen auf ein Forum mit Thema Programmierung: "Ein Code sagt mehr als tausend Worte" 🙂
(wobei mit Code hier nur der relevante Teil ohne Infrastruktur-Rauschen gemeint ist)

Es soll in einen Stream serialisiert werden und später daraus gelesen. Soll nun der Stream von Beginn an gelesen werden (als IEnumerable<T> als Rückgabe) od. eher "random access" im Stream?

Protobuf wurde schon erwähnt, aber das wurde wegem dem Schema (proto-files) eher abgelehnt. Wenn die (komplexen) Typen doch recht einfach sind, so ist die proto-File ebenfalls recht einfach.
Hast du an andere Formate wie MessagePack gedacht bzw. diese evaluiert?

Es wäre auch möglich die Daten per BinaryWriter in durch einen Zip-Stream (o.ä.) zu jagen, aber MessagePack, Protobuf sind hier i.d.R. überlegen, da sie speziell für solche Szenarien konzipiert wurden.

Nur zur Verdeutlichung / Beispiel: binäres Speichern eines int benötigt 4 byte (per Definition in C# / .NET). Protobuf hat hier eine Optimierung indem bei Werten aus dem Intervall [sbyte.MinValue, sbyte.MaxValue] nur das LSB gespeichert wird, also nur 1 byte benötigt wird. Für [short.MinValue, short.MaxValue], etc. analog.
Klar lässt sich das auch selbst so umsetzen, aber wenn es eine millionenfach genutze Komponente gibt, so ziehe ich diese vor, da mehr Entwicklung dorthin geflossen ist als ich selbst erreichen könnte. Von allfälligen Bugs und deren Fixes ganz zu schweigen.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

ISerializable habe ich in gut 15 Jahren vielleicht ein oder zwei mal verwenden oder nutzen müssen.
In der Regel kann man mit dem Serializable Attibute und einer ordentlichen Klasse nur für Serialisierung den Standard Fall herstellen.

Das ist mir bewusst. Die Frage war eher - welches ist "better practice", wäre eine der Variante der anderen vorzuziehen?

Ggf. verwalten diese auch nochmal intern eigene Zustände (Member) und erzeugen damit noch einen extra Overhead.

Die werden in meinem Falle doch aber gar nicht mitserialisiert - da es über ISerializable mache und dadruch ja kontrolliere, wasa ich serialisiere...

Je nachdem kannst du also noch Daten einsparen sowohl bei der Serialisierung bzw. Persistierung sowie bei der eigentlichen Datenhaltung im Speicher.
Ebenfalls kann man häufig durch Anpassung der Datentypen noch Speichernutzung vermindern.
Aber wie schon mehrmals gesagt müssten wir die genutzten Klassen kennen.

Die Speichernutzung an sich ist nicht mal das Problem - nur eben wenn ich es mit der Newtonsoft Library serialisiere - da kann ich aber erstmal nicht viel mehr machen, als diese eben nicht zu nutzen. Was später dann im weiteren Fortschritt des Programmes folgt, werde ich sehen - vermutlich muss ich dann nicht die komplette Liste halten sondern kann noch mal Filtern. Daher - es geht auch nicht um die Endlösung, sondern ist erstmal eher ein Zwischenschritt, um den ersten Schritt meines Algorithmus zwischenzuspeichern, um dann auf den Daten weiterarbeiten zu können ohne Schritt 1 jedesmal neu zu berechnen.

Aktuell hast du dich in ISerializable verbissen, weshalb schon viele weitere Ansätze komplett ausgeschlossen werden.
Dadurch nimmst du dir aber gerade mögliche Optionen, was dich selbst in deinen Möglichkeiten unnötig einschränkt.

Ich habe mich nicht darin verbissen, sondern lediglich gefragt, ob es alternativen zu BinaryFormatter bzw. BSON gibt, die diese (bereits implementierte) Schnittstelle nutzen. Wenn es das nicht gibt, dann muss ich eben einen anderen Weg gehen! 😉

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Da ich eine List<int> nicht als komplex bezeichnen würde, werden die konrkreten Typen wohl anders ausschauen, nur wie?

Ich meinte sowohl als auch. In meinem Programm triff das Problem mit komplexen Typen auf - man kann es aber genauso mit einer großen List<int> simulieren und beobachten. Freilich ist int kein komplexer Datentyp, das weiß ich schon ...

Es soll in einen Stream serialisiert werden und später daraus gelesen. Soll nun der Stream von Beginn an gelesen werden (als IEnumerable<T> als Rückgabe) od. eher "random access" im Stream?

Der Stream soll von beginn an gelesen werden. Random Access ist nicht notwendig.

Protobuf wurde schon erwähnt, aber das wurde wegem dem Schema (proto-files) eher abgelehnt. Wenn die (komplexen) Typen doch recht einfach sind, so ist die proto-File ebenfalls recht einfach.
Hast du an andere Formate wie MessagePack gedacht bzw. diese evaluiert?

Kann schon sein, dass Protobuf nicht so verkehrt wäre für meine Lösung - und ja ... eher abgeleht heißt nicht vollständig ausgeschlossen.
MessagePack hab ich angesehen - da bräuchte ich halt auch eine Surrogate-Klasse, da ich sonst die Attribute nicht einfügen kann. Oder kann MessagePack auch ISerializable nutzen und ich habe etwas übersehen?

Nur zur Verdeutlichung / Beispiel: binäres Speichern eines int benötigt 4 byte (per Definition in C# / .NET). Protobuf hat hier eine Optimierung indem bei Werten aus dem Intervall [sbyte.MinValue, sbyte.MaxValue] nur das LSB gespeichert wird, also nur 1 byte benötigt wird. Für [short.MinValue, short.MaxValue], etc. analog.
Klar lässt sich das auch selbst so umsetzen, aber wenn es eine millionenfach genutze Komponente gibt, so ziehe ich diese vor, da mehr Entwicklung dorthin geflossen ist als ich selbst erreichen könnte. Von allfälligen Bugs und deren Fixes ganz zu schweigen.

OK interessant. Pluspunkt für Protobuf.

Also vielen Danke erstmal (euch allen). Es ist auch nicht so, dass ich von euch eine fertige Lösung präsentiert haben möchte, sondern eher Anregungen, Vorschläge was in welchem Falle besser ist und was zu bedenken wäre, Vor- und Nachteile - die habe ich nun auch bekommen. Daher "wehrte" ich mich dagegen, meinen Code zu posten ... 😉

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

ISerializable hat halt einen anderen Zweck, bestimmte Use Cases. Habs ja oben schon genannt. Kannst ja problemlos auch ohne ISerializable serialisieren.
ISerializable heisst ja nur, dass Du eine manuelle Logik hast - nicht mehr, nicht weniger.

Ja genau. Ich weiß dass ich mit ISerializable eine manuelle Logik implementiere und ich weiß auch, das man ohne serialisieren kann. Ich hatte aber (wenn ich auch mal so die einschlägigen Seiten lese) den Eindruck (nur Eindruck), dass es er weniger/seltener genutzt wird und eher auf andere Wege gesetzt wird ... und frage mich daher warum?
Z.B. ist ja ein Nachteil, dass man mit ISerializable evtl. die Implementierung der Serialisierung ziemlich weit in seine Datenklassen mit reinzieht und in seine "elementaren Datenobjekte" nenn ich es jetzt mal - das finde ich eigentlich nicht so toll. Andererseits hat man das bei anderen Ansätzen eben durch die Attribute.

Aber wie gesagt, das ist eher eine generelle Wir brauchen da jetzt auch nicht vom 100 ins 1000 zu kommen.

Von daher ... vielen Dank auch Dir. Ich habe auf jeden Fall ein paar Anregungen bekommen.

6.911 Beiträge seit 2009
vor einem Jahr

Hallo backspeck42,

MessagePack hab ich angesehen - da bräuchte ich halt auch eine Surrogate-Klasse, da ich sonst die Attribute nicht einfügen kann. Oder kann MessagePack auch ISerializable nutzen und ich habe etwas übersehen?

Bei der Recherche nicht nur beim 1. gefundenen bleiben 😉
Es gibt ein paar Libs für .NET dazu.
Ziehe da auch die Möglichkeit von batch-basiertem Serialisieren in Betracht, sonst passiert wiederum alles im RAM auf einmal.

sondern eher Anregungen, Vorschläge was in welchem Falle besser ist und was zu bedenken wäre, Vor- und Nachteile - die habe ich nun auch bekommen. Daher "wehrte" ich mich dagegen, meinen Code zu posten

  • das hättest du schon zu Beginn schreiben können (dann hätte ich weniger schreiben können)
  • für den nächsten konkreten Fall gibt es vermutlich wieder andere Möglichkeiten die besser geeignet sind -- daher wozu die allgemeine Abhandlung?

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
backspeck42 Themenstarter:in
35 Beiträge seit 2019
vor einem Jahr

Bei der Recherche nicht nur beim 1. gefundenen bleiben 😉
Es gibt ein paar Libs für .NET dazu.

Ok, danke, da schau ich noch mal genauer hin.

Ziehe da auch die Möglichkeit von batch-basiertem Serialisieren in Betracht, sonst passiert wiederum alles im RAM auf einmal.

Ja so mache ich es momentan auch. Lustigerweise wird bei Newtonsoft dann im Hintergrund trotzdem erst das komplette Dokument gebaut und erst am Ende geschrieben.

das hättest du schon zu Beginn schreiben können (dann hätte ich weniger schreiben können)
für den nächsten konkreten Fall gibt es vermutlich wieder andere Möglichkeiten die besser geeignet sind -- daher wozu die allgemeine Abhandlung?

Hätte ich zu Beginn explizit schreiben können. Allerdings fragte ich ja recht allgemein und dachte daher, es wäre selbstklärend! 😉
Ja und die Allgemeine Abhandlung - ich finde das nicht von vorn herein schlecht - im Besten Falle hat man danach ein BIld im Kopf, welche Möglichkeiten für welche Fälle besser/schlechter geeignet sind. Wenn allerdings hier im Forum nur sehr konkrete fragen gewünscht sind, dann muss ich halt das nächste mal konkreter fragen ... 😉

6.911 Beiträge seit 2009
vor einem Jahr

Hallo backspeck42,

Wenn allerdings hier im Forum nur sehr konkrete fragen gewünscht sind

Das ist nicht der Fall. Es kann auch allgemein sein.
Nur sollte das fairerweise auch so deklariert werden -- die Leute hier helfen gerne und freiwillig (in ihrer Arbeitszeits od. Freizeit), das sollte man nicht überstrapazieren.

Aber genug damit, lass uns beim Thema bleiben.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"