Code: Select all
sourcefile.xml -> xslt1 -> xslt2 -> xslt3 -> xslt4 -> targetfile.xml
Wir sehen das folgende Muster mit einer Testquelldatei von 500 MB.
- Speicherbedarf mit nicht streambarem verkettetem SAX-Prozess: -Xmx 2GB
- Speicherbedarf für eine einzelne Streaming-Trafo-Phase: weniger als 200 MB, läuft gut mit -Xmx200M – das wäre perfekt.
- wenn wir die streambaren Trafos mit mehreren Trafos verketten .asDocumentDestination(nextTrafo) Wir benötigen 4 GB Speicher, um es auszuführen, andernfalls stoppt es mit „GC-Overhead-Limit überschritten“.
- getrennte Ausführung mit Xmx200M-Läufen für beide.
- verkettete Ausführung benötigt -Xmx4G zum Ausführen.
Wir könnten also natürlich zwischen den Trafos auf der Festplatte speichern und 4 separate Schritte haben, die jeweils 200 MB verbrauchen – aber ist das beim Streaming auf die Festplatte wirklich optimal? zwischen den Trafos?
Ist dieses Verhalten zu erwarten oder stimmt etwas mit unserer Implementierung nicht?
--- bearbeitet, weitere Informationen hinzugefügt scheint darauf hinzudeuten, dass Streaming auch in der Kette funktioniert Fall:
[*]Ich sehe eine teilweise geschriebene result.xml, selbst im verketteten Fall, wenn ich -Xmx500M setze, und erhalte einen OOM: etwa 10 % des erwarteten Werts result.xml befindet sich dort im Dateisystem.
[*]Ich sehe auch in den Protokollen, dass beide verketteten Trafos fast gleichzeitig gestartet werden – unmittelbar nach dem Kompilieren, und ich sehe ein laufendes Protokoll des zweiten trafo (eine Zeile für jeden verarbeiteten Dokument).
[*]Das laufende Protokoll startet schnell und wird dann etwa 15 Sekunden später langsamer (wenn GC anfängt zu schlagen) und stoppt schließlich kurz vor der OOM-Ausnahme.
Ich sehe nur, dass die drei kleinen Bäume (2x 500 Knoten, 1x 30000 Knoten) zum Laden statischer Zuordnungstabellen erstellt werden. Die gleichen Bäume werden erstellt, wenn ich einen einzelnen Streaming-Verkehr mit einer 500-MB-Quelle erfolgreich ausführe file und Der Kunde verwendet dies derzeit noch im Produkt.)
Wenn sich dadurch nichts ändert, werde ich den Fall reduzieren/isolieren und ein Support-Ticket eröffnen, wie Michael unten vorgeschlagen hat.
unser (vereinfachter) Code sieht so aus:
Code: Select all
// trafo1234 are Xslt30Transformer we got using xsltCompiler.compile().load30()
Serializer finalDest = trafo4.newSerializer(Files.newOutputStream(outFile));
StreamSource input = Files.newInputStream(inFile);
trafo1.applyTemplates(input,
trafo2.asDocumentDestination(
trafo3.asDocumentDestination(
trafo4.asDocumentDestination(finalDest))));