On iPadOS 26, PDFKit runs VNRecognizeDocumentsRequest over the pages of a PDFDocument
when those pages are rendered. The analysis pipelines are never released.
Measured on an iPad Pro 12.9-inch 4th gen (iPad8,11), iPadOS 26.6, with a 61-page image-only
scanned score: each newly-created-and-rendered PDFDocument costs about 2.7 OS threads and
20 MB, permanently. Repeatedly loading the same file from disk reached 153 threads and
1519 MB in under seven minutes, then died of an allocation failure.
Nothing releases it: not replacing PDFView.document, not deallocating the PDFView
entirely, not releasing the PDFDocument, and not time. With every code path in the app
stopped, the thread count does not fall — it continues to rise.
The stack
-[PDFView visiblePagesChanged:]
→ +[PDFPageAnalyzerV2 analyzePage:withBox:requestTypes:]
→ -[VNImageRequestHandler performRequests:gatheredForensics:error:]
→ -[VNRecognizeDocumentsRequest internalPerformRevision:inContext:error:]
→ -[VNDetector processUsingQualityOfServiceClass:options:regionOfInterest:…]
→ -[VNControlledCapacityTasksQueue dispatchSyncByPreservingQueueCapacity:]
Thread census at 1519 MB — 153 threads total, after 66 document loads:
66 PDFKit.PDFDocument.formFillingQueue
64 com.apple.VNRecognizeDocumentsRequestRevision1
10 ANEServicesThread
66 orphaned pipelines for 66 loads, all blocked on Vision's capacity limiter. The console
also emits Invalid permutation index when reordering subregions. Index N must be less than number of subregions 1 continuously, with N increasing — and these keep arriving after all
application activity has stopped.
Isolation
Each row is a separate run on the same device and OS, one variable changed. Counts are OS
threads; baseline is 13.
Configuration
Result
Page-stepping only on a stable document (~1000 visiblePagesChanged: events)
No growth; footprint declines
Recreating PDFThumbnailView on every load
No growth
Creating a PDFDocument and never rendering it
No growth
Creating + rendering, assigned to a PDFView
+2.0 to +2.7 threads / +20 MB per load
Creating + rendering, never assigned to any PDFView
Same growth
Creating + rendering, entire PDFView destroyed and rebuilt per load
Same growth
Two points worth drawing out:
The leak occurs with no PDFView involved at all — plain PDFPage.thumbnail(of:for:)
or PDFPage.draw(with:to:) on a freshly created document is sufficient.
Destroying the PDFView releases nothing. Whatever retains the analyses outlives
every object the application can reach.
Also, for anyone who arrives here from the other PDFPageAnalyzerV2 threads: the
usePageViewController(true, withViewOptions: nil) workaround does not help this. It reduces
visiblePagesChanged: frequency, and page changes on a stable document leak nothing. The
variable is newly rendered documents, not new pages.
The switch already exists
PDFView implements -setDocumentAnalysisEnabled: and -isDocumentAnalysisEnabled, plus
-handleAnalysisCompletionOfPage:resultTypes:. None of these appear in any public header.
With document analysis disabled, the leak disappears completely — 28 consecutive document
loads with zero thread growth, and after stopping, the process released down to 6 threads
and 64 MB, below its own idle baseline. It also suppresses the leak for documents never
assigned to that PDFView, so whatever the flag gates is not scoped to a single view.
For completeness, the per-page -setCandidateForOCR: / -setDidPerformOCR: accessors do
not help: the writes land and read back correctly, and the analysis runs anyway. They
appear to be state rather than policy.
Request
Either:
Fix the leak — cancel and release analyses when the document or the view goes away; or
Make documentAnalysisEnabled public on PDFView (or add an equivalent on
PDFDocument).
Ideally, please do both.
The second costs Apple nothing: the property exists, it works, and it is exactly the control
that is needed. Applications that render sheet music, engineering drawings, or any other
content where document understanding provides no value are currently paying for it with
unbounded memory growth and no supported way to decline.
Filed as FB24211659. Happy to share the isolation harness with anyone from the PDFKit team.
Related: 825803 (crash in PDFPageAnalyzerV2, FB22409977), 827781 (deadlock in the same
class), 838272 / 837282 (PDFTileSurface over-release), 107007 (CGContextDrawPDFPage
thread safety, open since 2018).
0
0
9