Hi Tilman, Thanks for your reply and for opening an issue.
> I assume what you did was to check the gsubWorkers map before calling > gsubWorkerFactory.getGsubWorker(), correct? > Not exactly. I should have included my patch/"hack" in the original message for more clarity. I'm basically simply adding a global cache for the GlyphArraySplitter, inside GsubWorkerForLatin. I left setFont and the gsubWorkers map alone. It is built in applyGsubFeature (once per showText), not in the constructor, so reusing the GsubWorker alone would not stop the rebuild and the performance hit. I memoized the GlyphArraySplitter per font and then per script feature (I think this is correct, but I'm not 100% sure). The whole change is one line in applyGsubFeature: - GlyphArraySplitter glyphArraySplitter = new GlyphArraySplitterRegexImpl(scriptFeature.getAllGlyphIdsForSubstitution()); + GlyphArraySplitter glyphArraySplitter = splitterFor(scriptFeature); https://github.com/apache/pdfbox/blob/3.0.4/fontbox/src/main/java/org/apache/fontbox/ttf/gsub/GsubWorkerForLatin.java#L91-L92 Plus a static cache keyed on the font's GsubData and a small helper: private static final Map<GsubData, Map<String, GlyphArraySplitter>> SPLITTER_CACHE = new WeakHashMap<>(); private GlyphArraySplitter splitterFor(ScriptFeature scriptFeature) { synchronized (SPLITTER_CACHE) { Map<String, GlyphArraySplitter> perFont = SPLITTER_CACHE.get(gsubData); if (perFont == null) { perFont = new HashMap<>(); SPLITTER_CACHE.put(gsubData, perFont); } GlyphArraySplitter splitter = perFont.get(scriptFeature.getName()); if (splitter == null) { splitter = new GlyphArraySplitterRegexImpl(scriptFeature.getAllGlyphIdsForSubstitution()); perFont.put(scriptFeature.getName(), splitter); } return splitter; } } This is a proof of concept, of course. This was just to convince myself that rebuilding GlyphArraySplitter multiple times was indeed the problem I was observing. On larger PDF files (dozens of pages), the speedup with the code above is really huge (3-4x on the total PDF generation times). Thanks, Olivier
