Arbeitsspeicher und Streaming
Spec: ISO 32000-2, §7.5.4 ISO 32000-2 §7.5.4 Evidence: Mixed evidence
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Ein großes PDF sollte keinen großen Arbeitsspeicher erfordern. Diese Seite erklärt, wie NextPDF den Prozess-Heap begrenzt hält, während ein Dokument wächst, an welchen Stellen es auf die Festplatte streamt statt Daten anzuhäufen und was ein „Performance-Budget“ hier bedeutet: ein geprüfter Vertrag, keine plakative Zahl.
Warum das wichtig ist
Abschnitt betitelt „Warum das wichtig ist“Das PDF-Format zwingt einen Generator nicht dazu, viel Arbeitsspeicher zu verwenden. Seine Querverweistabelle erfasst für jedes indirekte Objekt einen Byte-Offset, sodass ein Reader nur wahlfreien Zugriff auf die Datei benötigt und nicht die gesamte Datei im Arbeitsspeicher halten muss. Ein Generator kann dieses Muster übernehmen: Er kann Objekte ausgeben, sobald sie fertiggestellt sind, und muss sich nur merken, wo sie gelandet sind. Bleibt stattdessen das gesamte Dokument bis zum abschließenden Schreiben im Heap, treibt die Seitenzahl den Arbeitsspeicher linear in die Höhe, und ein Bericht, der bei hundert Seiten noch problemlos ist, lässt den Prozess bei fünfzigtausend scheitern.
Bei Batch- und Worker-Workloads ist das der Unterschied zwischen einem stabilen Dienst und einem, der unter Last unvorhersehbar ausfällt. Begrenzter Arbeitsspeicher ist eine gezielt zu entwerfende Design-Eigenschaft, keine Zahl, auf die man hofft.
Die Kurzfassung
Abschnitt betitelt „Die Kurzfassung“- Der Streaming-Writer ist so gebaut, dass der Arbeitsspeicher pro Dokument begrenzt bleibt. Jede Seite wird in die Ausgabe geschrieben, sobald sie finalisiert ist. Anschließend wird ihr Puffer freigegeben.
- Die Buchführung, die andernfalls mit der Objektanzahl wachsen würde – die Querverweis-Offsets und die
Kids-Verweise des Seitenbaums –, wird in temporäre Streams geschrieben, die mitphp://temp/maxmemory:0geöffnet werden und sofort auf die Festplatte auslagern, statt den PHP-Heap zu füllen. - Das Designziel ist O(1)-Heap pro Seite: Das Vorhalten des Dokuments wird nicht teurer, wenn Seiten hinzukommen. An diesem technischen Ziel ist der Writer ausgerichtet.
- Ein Performance-Budget ist ein echtes, strukturiertes Konzept im Dokumentationssystem: eine Obergrenze für die Wall-Clock-Zeit und eine Obergrenze für den Spitzen-Arbeitsspeicher, formuliert als geprüfter Vertrag. Es benennt eine Verpflichtung. Es ist kein Benchmark-Ergebnis.
- Konkrete Zahlen werden als lebendes Signal behandelt: nach einer angegebenen Methode gemessen und nicht in Prosa eingefroren, wo sie unbemerkt veralten könnten.
Wie NextPDF dabei vorgeht
Abschnitt betitelt „Wie NextPDF dabei vorgeht“Die gesamte Form des Streaming-Writers ergibt sich aus einer Entscheidung: Niemals zurückhalten, was ausgegeben werden kann.
- Start page A single active cursor; no document-wide page graph in memory.
- Finalise page Page content + page object written straight to the output stream.
- Release buffer The finalised page buffer is dropped; the heap returns to baseline.
- Record offset to disk Xref and Kids entries go to php://temp/maxmemory:0 — immediate disk spill.
- Close Pages-tree root, Catalog, and trailer written once at the end.
Entscheidend ist das Auslagern auf die Festplatte. PHPs php://temp hält eine kleine Menge im Arbeitsspeicher und lagert erst aus, wenn ein Schwellenwert überschritten wird. Der Writer öffnet diese temporären Streams mit der Option maxmemory:0, die sie zwingt, sofort auszulagern – der Schwellenwert im Arbeitsspeicher ist null. Der praktische Effekt ist, dass sich die Pro-Objekt-Buchführung, die per Definition mit dem Dokument wächst, niemals im Heap ansammelt. Sie sammelt sich auf der Festplatte an, wo die Größe nicht der begrenzende Faktor ist. Ohne diese Option müsste sich das standardmäßige Arbeitsspeicher-Fenster erst füllen, bevor ausgelagert wird, was das Ziel des begrenzten Arbeitsspeichers genau dann unterlaufen würde, wenn es am wichtigsten ist.
Das Performance-Budget ist der zweite Teil der Geschichte, und es ist ein Vertrag des Dokumentationssystems statt einer Marketing-Behauptung. Das Schema definiert ein Budget als zwei begrenzte Ganzzahlen: eine Obergrenze für die Wall-Clock-Zeit in Millisekunden und eine Obergrenze für den residenten Spitzen-Arbeitsspeicher in Mebibyte. Ein Rezept, das ein Budget deklariert, deklariert eine überprüfbare Verpflichtung – genauso wie eine typisierte Signatur eine Verpflichtung deklariert, die ein Compiler prüfen kann. Der Wert eines Budgets liegt darin, dass es benannt und durchgesetzt ist, nicht darin, dass es klein ist.
Was die Belege sagen
Abschnitt betitelt „Was die Belege sagen“Diese Seite ist Evidence: Mixed evidence , und die Mischung ist bewusst gewählt, weil die Belege tatsächlich drei unterschiedliche Arten haben.
- Codegestützter Mechanismus. Der Streaming-Writer in
src/Writer/Streaming/StreamingPdfWriter.phpdokumentiert und implementiert den Pro-Seite-Zyklus nach dem Muster Ausgeben-dann-Freigeben und öffnet seine Xref- und Kids-Streams mitphp://temp/maxmemory:0, um sofortiges Auslagern auf die Festplatte zu erzwingen, sodass der PHP-Arbeitsspeicher unabhängig von der Objektanzahl begrenzt bleibt. Das streamende Design mit einem einzigen Cursor und ohne zurückgehaltenen Baum ist außerdem die in ADR-001 festgehaltene Architekturentscheidung (die Rendering-Pipeline hält höchstens O(Tiefe)-Zustand, nicht O(n) Knoten). - Designprinzip-Budget. Das Feld
performance_budgetist ein echter, optionaler Bestandteil des Dokumentationsschemas, definiert als{ wall_ms, peak_mb }mit expliziten Obergrenzen. Es ist per Design ein durchsetzbarer Vertrag. - Benchmark als lebendes Signal. ADR-001 stellt ausdrücklich klar, dass die unter kontrollierten Bedingungen ermittelten Spitzen-Arbeitsspeicher- und Wall-Clock-Werte für große Dokumente ein empirisches Ziel sind, das nach einer angegebenen Methode erhoben und festgehalten wird – keine Zahl, die in Prosa behauptet wird. Diese Seite benennt daher den Mechanismus und den Vertrag und verweist für konkrete Zahlen auf die Stelle, an der sie gemessen werden.
Das Format macht dieses Ziel plausibel statt bloß aspirativ. Da die Querverweistabelle gemäß Spec: ISO 32000-2, §7.5.4 ISO 32000-2 §7.5.4 einen Byte-Offset pro indirektem Objekt erfasst, ist ein Generator in der Lage Objekte zu schreiben, sobald er sie fertigstellt, und nur ihre Offsets zu behalten. Begrenzter Arbeitsspeicher steht im Einklang mit dem Dateiformat, nicht im Widerstreit mit ihm.
Praktisches Beispiel
Abschnitt betitelt „Praktisches Beispiel“Begrenzter Arbeitsspeicher ist eine Eigenschaft der Art und Weise, wie Sie generieren, kein Schalter, den Sie setzen. Eine Batch-Schleife, die jedes Dokument finalisiert und freigibt, hält den Heap über den gesamten Lauf flach:
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Core\PdfFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// Process-lifetime, shared once.$factory = PdfFactory::new() ->withCompress(true) ->withDocumentFactory(new DocumentFactory( new FontRegistry(), new ImageRegistry(maxCacheBytes: 50 * 1024 * 1024), ));
// Per-document, created and released each iteration.foreach ($invoiceBatch as $invoice) { $doc = $factory->create(); $doc->addPage(); $doc->writeHtml($invoice->toHtml()); $doc->save($invoice->outputPath()); unset($doc); // the document model is not carried into the next iteration}Die Registries werden gemeinsam genutzt, weil das einmalige Parsen von Schriften und Bildern der Sinn eines Workers ist. Das Dokument wird nicht gemeinsam genutzt und bei jedem Durchgang freigegeben – dadurch bleibt der Batch-Arbeitsspeicher auf ein Dokument begrenzt und wächst nicht mit dem gesamten Batch.
Häufiges Missverständnis
Abschnitt betitelt „Häufiges Missverständnis“Das häufigste Missverständnis besteht darin, „begrenzten Arbeitsspeicher“ als Benchmark-Aussage zu behandeln – also eine Megabyte-Zahl zum Zitieren zu erwarten. Damit wird die Aussage verdreht. Die Garantie hier ist strukturell: Der Writer ist so gebaut, dass das Halten eines Dokuments nicht mehr kostet, wenn Seiten hinzugefügt werden. Eine konkrete Spitzenzahl hängt vom Seiteninhalt, von den Schriften und den Bildern ab und ist nur mit der zugehörigen Messmethode aussagekräftig – deshalb gehört sie zu einem Benchmark und nicht in diese Aussage.
Eine zweite Falle: anzunehmen, php://temp schütze Sie bereits. Das tut es – aber erst, nachdem sich sein standardmäßiges Arbeitsspeicher-Fenster gefüllt hat. Die Option maxmemory:0 erzwingt das sofortige Auslagern. Dieses Detail ist der Mechanismus. Ohne sie würde die Eigenschaft genau bei den großen Dokumenten nicht halten, für die sie existiert.
Grenzen und Abgrenzungen
Abschnitt betitelt „Grenzen und Abgrenzungen“Diese Seite erklärt den Streaming-Mechanismus und die Bedeutung eines Performance-Budgets. Sie benennt keine gemessenen Spitzen-Arbeitsspeicher- oder Durchsatz-Werte. Diese entstehen in der Benchmarking-Disziplin nach einer angegebenen Methode, und ADR-001 verweist die empirischen Zahlen ausdrücklich auf diese Messung. Begrenzt „pro Dokument“ bedeutet nicht, dass der Speicherverbrauch unabhängig vom Inhalt eines einzelnen Dokuments konstant bleibt: Eine Seite mit vielen großen eingebetteten Bildern beansprucht weiterhin den Speicher, den diese Bilder benötigen. Was nicht wächst, ist die Pro-Seite-Buchführung und der zurückgehaltene Seitengraph. Nicht jeder Generierungspfad ist der Streaming-Writer. Welche Pfade streamen und welche puffern, wird durch den Code und die Form der Pipeline bestimmt, nicht durch diese Übersicht. Der beschriebene Mechanismus ist zum Prüfdatum dieser Seite zutreffend. Die maßgeblichen Quellen sind src/Writer/Streaming/ und ADR-001 im Core-Repository.
Das Design aus Streaming und begrenztem Arbeitsspeicher ist eine Core-Eigenschaft. Editionen ändern das nicht:
| Edition | Availability |
|---|---|
| Core | Core stellt das streamende, auf die Festplatte auslagernde Writer-Design bereit. |
| Pro | Pro erbt denselben Writer mit begrenztem Arbeitsspeicher; es fügt Funktionen hinzu, kein anderes Speichermodell. |
| Enterprise | Enterprise erbt denselben Writer mit begrenztem Arbeitsspeicher; es fügt Funktionen hinzu, kein anderes Speichermodell. |
Verwandte Dokumentation
Abschnitt betitelt „Verwandte Dokumentation“- Das Pipeline-Modell – wo die Writer-Stufe im Dokumentfluss eingeordnet ist.
- Ehrliches Benchmarking – wie NextPDF die Zahlen ausweist, die diese Seite bewusst nicht behauptet.
- Hochvolumige Dokumenterzeugung – das Batch-Szenario, für das dieser Mechanismus gebaut ist.
Glossar
Abschnitt betitelt „Glossar“- Begrenzter Arbeitsspeicher – eine Design-Eigenschaft, bei der das Vorhalten des Dokuments nicht mehr Heap verbraucht, wenn Seiten hinzugefügt werden (das O(1)-pro-Seite-Ziel).
- Streaming-Writer – der Writer, der jede Seite in die Ausgabe schreibt und ihren Puffer freigibt, statt das gesamte Dokument zurückzuhalten.
php://temp/maxmemory:0– ein temporärer PHP-Stream, der so konfiguriert ist, dass er sofort auf die Festplatte auslagert; verwendet für die wachsende Pro-Objekt-Buchführung.- Performance-Budget – ein strukturierter Dokumentationsvertrag: eine Obergrenze für die Wall-Clock-Zeit und eine Obergrenze für den Spitzen-Arbeitsspeicher, benannt und überprüfbar.
- Lebendes Signal – ein gemessener Wert, der mit seiner Methode unter angegebenen Bedingungen ausgewiesen wird, anstatt als feste Zahl in Prosa eingebettet zu sein.