This is an automated email from the ASF dual-hosted git repository. tballison pushed a commit to branch TIKA-4868-performance-improvements in repository https://gitbox.apache.org/repos/asf/tika.git
commit 967e988c59b956d923b9ffdbf1b0c4eaac86a05b Author: tallison <[email protected]> AuthorDate: Wed Sep 2 08:11:29 2026 -0400 fix zip rewind re-decompression --- CHANGES.txt | 8 ++++++++ .../main/java/org/apache/tika/parser/pkg/ZipParser.java | 14 +++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 0e6e1ad587..7744bb009c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,13 @@ Release 4.1.0 - unreleased + * ZipParser no longer re-decompresses an entry on every rewind when the + entry uses a legacy compression method (implode, shrink, bzip2, ...): + those decode per-bit, so the rewind-by-reopen trade that works for + STORED/DEFLATED entries re-decoded the whole entry for each of the + several rewinds the embedded pipeline performs. Such entries now + replay from the budgeted cache. An imploded 606KB zip drops from + 610ms to 102ms in tika-server (TIKA-4868). + * More detection/dispatch savings: the message/rfc822 priority-45 magic is gated behind a ':' scan of the first 30 bytes (every match provably has one, so results are unchanged and non-mail text skips its ~40 diff --git a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java index 58e703d79d..405bb314bb 100644 --- a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java +++ b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java @@ -497,9 +497,17 @@ public class ZipParser extends AbstractArchiveParser { if (extractor.shouldParseEmbedded(entryMetadata, context)) { TemporaryResources tmp = new TemporaryResources(); // Re-openable source: rewind (e.g. for digesting) re-opens the entry instead of - // buffering/spilling it - try (TikaInputStream tis = TikaInputStream.get( - () -> zipFile.getInputStream(entry), tmp, entryMetadata)) { + // buffering/spilling it. That trade only holds when re-opening is cheap -- + // STORED and DEFLATED. The legacy methods (implode, shrink, bzip2, ...) decode + // per-bit, so a re-open re-decompresses the whole entry for every rewind; + // those route through the budgeted cache instead (memory up to the + // CacheMemoryBudget, temp spill beyond it). + int method = entry.getMethod(); + boolean cheapReopen = method == java.util.zip.ZipEntry.STORED + || method == java.util.zip.ZipEntry.DEFLATED; + try (TikaInputStream tis = cheapReopen + ? TikaInputStream.get(() -> zipFile.getInputStream(entry), tmp, entryMetadata) + : TikaInputStream.get(zipFile.getInputStream(entry), tmp, entryMetadata)) { extractor.parseEmbedded(tis, xhtml, entryMetadata, context, true); } catch (UnsupportedZipFeatureException e) { EmbeddedDocumentUtil.recordEmbeddedStreamException(e, parentMetadata, context);
