Zstd: Besseres Komprimierungsverhältnis, wenn der Komprimierungskontext regelmäßig verworfen wird

Erstellt am 8. Juli 2019  ·  3Kommentare  ·  Quelle: facebook/zstd

Ich erhalte durchweg ein etwas besseres Komprimierungsverhältnis, wenn der Komprimierungskontext nicht wiederverwendet wird.
Ich erstelle einen ZSTD-Komprimierungskontext und rufe dann in einer Schleife ZSTD_compressCCtx auf, wobei jedes Mal 1 MB Puffer mit Daten angegeben wird. Am Ende des Prozesses wird der Komprimierungskontext freigegeben.
Wenn ich den Komprimierungskontext freigebe und einen neuen erstelle, bevor ich mit dem nächsten 1-MB-Puffer komprimiere, ist die Größe der Ausgabedatei durchweg um 1% kleiner.
Eine weitere interessante Tatsache ist, dass das Komprimierungsverhältnis um 1 - 1,5% besser ist, wenn ich 2-MB-Eingangspuffer mit Daten verwende, verglichen mit 1-MB-Eingangspuffern.
In meinem Anwendungsfall bin ich nicht durch Speicherressourcen beschränkt.
Fragen)

  • Ist es besser, den Komprimierungskontext zwischen dem Komprimieren großer Datenblöcke zu verwerfen?

    • Was wird für eine optimale Eingabepuffergröße empfohlen (dh eine Verringerung der Puffergröße verschlechtert das Komprimierungsverhältnis, während eine Erhöhung der Puffergröße das Komprimierungsverhältnis nicht verbessert)?

    • Jede Möglichkeit, zstd mitzuteilen, "verwenden Sie so viel Speicher, wie Sie möchten, aber geben Sie mir ein besseres Komprimierungsverhältnis und / oder eine bessere Geschwindigkeit".

    • Ist die Streaming-Komprimierung mit Kontext wirklich nur für Anwendungsfälle mit eingeschränktem Speicher geeignet? Wenn ich viel Speicher habe, bin ich besser dran, wenn ich große (> 1 MB) Puffer unabhängig komprimiere?

question

Alle 3 Kommentare

Hallo @scherepanov ,

Dieses Ergebnis ist überraschend.
Bei Verwendung von ZSTD_compressCCtx() mit derselben Eingabe und derselben Komprimierungsstufe sollte es (aus Sicht des Komprimierungsverhältnisses) keine Rolle spielen, ob der Kontext wiederverwendet wird oder nicht. Die einzige Auswirkung der Wiederverwendung des Kontexts besteht darin, Zuordnungs- und Initialisierungszeit zu sparen. Wenn es das Komprimierungsverhältnis beeinflusst, ist es seltsam und wahrscheinlich falsch.

Ich würde dieses Szenario gerne reproduzieren, wenn das möglich ist. Welche Version verwenden Sie?

Ist es besser, den Komprimierungskontext zwischen dem Komprimieren großer Datenblöcke zu verwerfen?

Sie sollten niemals den Kontext verwerfen müssen.
Der einzige "gute" Grund dafür ist die Vereinfachung des Codes.
Aus Sicht der Leistung sollte dies jedoch nur von Vorteil sein, kein Nachteil.

Was wird empfohlen, optimale Eingabepuffergröße

Dies ist sehr situativ. Es gibt keine "universelle" Schwelle.
Im Allgemeinen ist eine Erhöhung der Blockgröße über die 8-fache Fenstergröße hinaus immer weniger wertvoll.
Die Fenstergröße ist jedoch ein dynamischer Wert, abhängig von der Komprimierungsstufe.
Sie variiert zwischen 512 KB (Stufe 1) und 8 MB (Stufe 19).

Jede Möglichkeit, zstd zu sagen, "benutze so viel Speicher wie du willst, aber gib mir ein besseres Komprimierungsverhältnis"

Level 19 soll von dieser Art sein

und / oder Geschwindigkeit "

Level 4 ist im Allgemeinen von dieser Art: Es komprimiert ziemlich schnell, verwendet aber eine übergroße Menge an Speicher. Das ist das Nächste, was ich mir vorstellen kann.

Ist die Streaming-Komprimierung mit Kontext wirklich nur für Anwendungsfälle mit eingeschränktem Speicher geeignet? Wenn ich viel Speicher habe, bin ich besser dran, wenn ich große (> 1 MB) Puffer unabhängig komprimiere?

Das Komprimieren / Dekomprimieren unabhängiger Blöcke in einem einzigen Durchgang ( ZSTD_compressCCtx() und ZSTD_decompressDCtx() ) ist einfach einfacher und wahrscheinlich so effizient wie möglich. Wenn Sie es schaffen, ist es vorzuziehen. Der Streaming-Modus erhöht die Komplexität zusätzlich. Die Komplexität ist größtenteils intern und verborgen, aber die Hauptidee ist, dass sie nicht besser / schneller sein kann als die einfache Komprimierung oder Dekomprimierung in einem Durchgang.

Vielen Dank für die sehr klare Antwort.
Ich habe ein unterschiedliches Komprimierungsverhältnis auf eine unterschiedliche Reihenfolge meiner Daten zurückgeführt. Ja, die Wiederverwendung von Kontext und das Verwerfen machen keinen Unterschied, genau wie Sie gesagt haben. Entschuldigung, ich sollte vorsichtiger sein und mehr Nachforschungen anstellen, bevor ich Fragen einreiche.
Ihre Kommentare sind sehr klar und sehr erklärend. Ich denke, es muss wirklich zu Dokumenten hinzugefügt werden. Besonders wichtig ist der Unterschied zwischen Streaming und Nicht-Streaming. Ich war immer der Meinung, dass Streaming effizienter ist, da Sie das Wörterbuch besser erstellen können (obwohl nicht klar ist, wie Sie das Wörterbuch ändern, wenn sich Daten in einer Datei ändern). Es ist sehr wichtig zu verstehen, dass Streaming so ziemlich mit "blockbasierter" Komprimierung identisch ist. Auf der anderen Seite kann das Streaming effizienter sein, da Sie die Blockgröße automatisch verarbeiten. Ich verwende eine Blockgröße von 1 MB mit der Standardkomprimierungsstufe 3 und scheine nicht ausreichend zu sein, um eine bessere Komprimierung zu erzielen. Unter diesem Gesichtspunkt kann Streaming das Komprimierungsverhältnis effizienter gestalten, da Sie die Blockgröße optimaler bestimmen. (Ist das richtig???)

Streaming ist so ziemlich das Gleiche wie "blockbasierte" Komprimierung

Es ist nicht genau "das gleiche".

Wenn Sie Eingabedaten in Blöcke schneiden und diese unabhängig an ZSTD_compressCCtx() , erhalten Sie mehrere unabhängige komprimierte Blöcke. Jeder komprimierte Block ist ein unabhängiger Frame. Sie können in beliebiger Reihenfolge dekomprimiert werden, da jeder Frame unabhängig ist.

Wenn Sie dieselben Daten mit ZSTD_compressStream() ohne Chunking in einen einzelnen Stream senden, erhalten Sie einen einzelnen Frame. Intern wird der Rahmen in Blöcke geschnitten, ja, aber das spielt keine Rolle, da Blöcke nicht unabhängig sind. Um einen Teil des Rahmens zu dekodieren, muss alles von Anfang an dekodiert werden.

Theoretisch sollte ein einzelner Frame besser komprimiert werden als mehrere unabhängige Frames. Dies liegt daran, dass beim Schneiden von Daten in mehrere unabhängige Blöcke zu Beginn jedes Blocks einige Komprimierungsmöglichkeiten verloren gehen.
Schnelle Modi sind jedoch lediglich "probabilistische" Kompressoren, die voreilige Wetten abschließen, um schnell zu laufen. Nicht alle Opportunities sind gleich, und manchmal maskiert die Auswahl einer Opportunity nur eine spätere bessere Opportunity. Dies ist sehr datenspezifisch.
In einigen seltenen Fällen kann es daher vorkommen, dass das Schneiden von Daten in unabhängige Blöcke mit einem einzigen Stream konkurriert.
Aber darauf würde ich nicht wetten. In den meisten Fällen sollte ein einzelner Stream gewinnen, wenn auch nur sehr wenig.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen