Ein eigenes Binärformat schrumpft JSON um 80%
Packing Binary Is Fun
Inspiriert von einer Twitter-Diskussion, dass echte Entwickler keine JSON-Daten speichern, baute der Autor jBin – eine komplette binäre Schema-Sprache. Statt nur Bytes zu schreiben, entstand ein varint-basiertes Format mit Continuation-Bits, Typ- und Feldnummern in einem einzigen Byte. Das Ergebnis: JSON-Payloads schrumpfen um bis zu 80%. Der Artikel erklärt Schritt für Schritt, wie aus einem simplen 'wb' ein ausgeklügeltes Serialisierungssystem wurde.
Nun, wenn wir es entfernen, woher weiß unser binärer Leser dann, wo der Header endet? Er braucht eine Möglichkeit zu sagen: „Okay, der Header ist fertig, fang jetzt an, die eigentlichen Daten zu lesen.“
- trashb
Ich vermisse einige wichtige Teile, von denen ich behaupten würde, dass sie jedes (binäre) Format braucht.
- einen Magic-Header
- eine Versionsnummer
- eine CRC- oder Datenkorruptionsprüfung
Zusätzlich würde ich behaupten, dass man in diesem Fall besser dran wäre, einen eigenen Textparser zu schreiben, anstatt ein binäres Format zu parsen; das ist ähnlich wie die Debatte über unixartige Konfiguration vs. Windows regedit. Ich würde etwas anderes als json bevorzugen, aber trotzdem als txt lesbar.
Selbst das unten angegebene json-Beispiel kann von 418 Zeichen auf 166 reduziert werden, indem man die Feldnamen durch einzelne Zeichen ersetzt und die Leerzeichen entfernt. Fast die gesamte Einsparung in diesem Format kommt daher, dass die Feldnamen nicht enthalten sind und das Layout positionsabhängig ist. Man kann sich entscheiden, Trennzeichen zu verwenden oder dafür zu sorgen, dass ein Byte den Typ (+Größe) angibt, zum Beispiel kodiert die folgende Zeichenkette die Beispieldaten fast (85 Bytes vs. 80 Bytes) so effizient, ist aber immer noch lesbar und unterstützt utf-8-Interpretation.
123456789;LeroyJenkins;60;alliance;p,100,200,300;i,999,1,1;i,45,100,0;a,s,120;a,a,45;
Man kann es weiter optimieren, indem man wiederkehrende Einträge erlaubt und Annahmen von einem definierten Standardwert zulässt und nur Deltas sendet, was vom erwarteten Datentyp abhängen kann.
{ "itemId": 999, "quantity": 1, "isSoulbound": false }
i,999,1,0
könnte werden zu:
default = { "itemId": 0, "quantity": 1, "isSoulbound": false }
{ "itemId": 999}
i,999
- ErikHuisman
Ich will auch ein echter Entwickler sein, also GZIPPE ich einfach das JSON, um es binär zu machen.
- Skwid
Eines meiner liebsten Yak-Shaving-Abenteuer in einem früheren Job war das Schreiben eines Parse-in-Place-UBJSON-Decoders für ~1 MB Daten auf einem Gerät mit etwa genauso viel freiem Speicher. Schneller (genug) Zugriff per Schlüssel, binäre Suche mit ein paar Abkürzungen für die größtenteils numerische Nutzlast.
Er baute einen Index von vielleicht 30 Bytes auf, um die Sache zu beschleunigen, aber auch, damit er weiter am Ende der alten Nachricht arbeiten konnte, während die neue deren Anfang überschrieb.
Hätte das Systemdesign all das von einem Gerät mit 4 MB Speicher verlangen sollen? Wahrscheinlich nicht. Aber es funktionierte, und ich hatte eine großartige Zeit