`PdfSmartCopy` can take effectively unbounded time on nested shared Form XObjects
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- java
- Ambito
- backend, performance
Direzione di ricerca
Start in PdfSmartCopy.ByteStore, which the issue identifies as recursively traversing shared indirect objects during deduplication. Use the provided createPdfWithNestedFormXObjects example to reproduce the slowdown, then compare processing with PdfCopy. Done when PdfSmartCopy handles the shared nested Form XObjects without the reported excessive time and memory use.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
Using PdfSmartCopy to process a valid PDF with Form XObjects that reference nested resource dictionaries that repeatedly contain many Form XObjects from the next level can take a long time and use a lot of memory even for relatively small files. The problem seems to be that, in order to perform deduplication, PdfSmartCopy.ByteStore recursively traverses shared indirect objects once for every path through the resource graph, without keeping track of already-serialized indirect objects.
Important to note that using PdfCopy to process the same kind of file works fine, without taking too long or using too much memory.
To Reproduce
The document that triggered the issue cannot be shared because it contains private information. It is a 11 page document of roughly 300 KB, generated by the library TCPDF 6.7.5. The following code generates a 1 page pdf document that demonstrates the issue:
private void test() {
var pdfBytes = createPdfWithNestedFormXObjects(8, 8);
try (var doc = new Document(); var out = new ByteArrayOutputStream(); var copy = new PdfSmartCopy(doc, out)) {
doc.open();
copy(pdfBytes, copy);
}
}
void copy(byte[] bytes, PdfCopy copy) throws Exception {
try (var reader = new PdfReader(bytes)) {
for (var page = 1; page <= reader.getNumberOfPages(); page++) {
copy.addPage(copy.getImportedPage(reader, page));
}
}
}
private byte[] createPdfWithNestedFormXObjects(int nestedLeves, int fanout) throws Exception {
var output = new ByteArrayOutputStream();
var document = new Document(PageSize.A4);
var writer = PdfWriter.getInstance(document, output);
document.open();
document.add(new Paragraph("Test PDF, nested Form XObjects"));
List<PdfTemplate> layer = new ArrayList<>();
for (var index = 0; index < fanout; index++) {
var leaf = PdfTemplate.createTemplate(writer, 20, 20);
leaf.rectangle(0, 0, 10, 10);
leaf.stroke();
layer.add(leaf);
}
for (var level = 1; level < nestedLeves; level++) {
var parents = new ArrayList<PdfTemplate>();
for (var index = 0; index < fanout; index++) {
var parent = PdfTemplate.createTemplate(writer, 20, 20);
for (var nested : layer) {
parent.addTemplate(nested, 0, 0);
}
parents.add(parent);
}
layer = parents;
}
for (var form : layer) {
writer.getDirectContent().addTemplate(form, 0, 0);
}
document.close();
return output.toByteArray();
}
Varying the parameters of createPdfWithNestedFormXObjects allows to see the cases that trigger the problem.
Expected behavior
Using PdfSmartCopy should take more or less the same amount of time and use more or less the same amount of memory of using PdfCopy to process a document with multple levels of Form XObjects that reference shared Form XObjects.
System
- OpenPDF version: 3.0.3, 3.0.4, 3.0.5
- Lingua principale
- Java
- Stelle
- 4.4k
- Fork
- 714
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di LibrePDF/OpenPDF
-
bug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
-
IndexOutOfBoundsException in PdfReaderForse già presa @andreasrosdalw l’ha presa 93 giorni fa. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
-
enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 38/100
-
Difficoltà 4/5 1-2 giorni Idoneità per principianti 45/100
Tutte le issue di LibrePDF/OpenPDF
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
quarkiverse/quarkus-google-cloud-services#1187 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 82/100
locationtech/jts#1250 ·
-
type/improve
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 71/100
linagora/twake-calendar-side-service#1235 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Good First Issue
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 75/100
hiero-ledger/hiero-sdk-java#3025 ·
I maintainer di solito rispondono entro 1 giorno