PdfPooledRenderWorker class
Fans record calls across a fixed set of platform workers so up to N pages decode at once instead of one at a time. A single worker serializes every page; on a document whose sheets are each a multi-second image decode that makes the tail crawl. Spreading the work across a pool drains it ~N× faster - the visible burst on load and the background prefetch alike.
New records are dispatched to the least-loaded active worker, where load is
the number of queued or in-flight records this pool has handed that worker.
A static page % N mapping is used only as the tie-break/fallback, so a
cluster of heavy pages that would all hash to one worker can spill onto idle
siblings. While a (page, priority) record is outstanding, later records for
the same pair reuse its worker; cancel routes through that lease table so
it still reaches the worker holding the queued request.
Speculative work (priority greater than zero) may occupy at most N−1 active workers. The final idle lane is left available for a visible request: pure Dart image decoding is synchronous, so a worker inside a large JPEG cannot observe a cooperative cancellation message until the expensive decode returns. This dynamic reservation adds no worker or document copy, and it disappears for a one-worker pool. Priority zero and negative priorities are foreground and may use the whole pool.
Each worker opens its own copy of the document, but the pool does NOT hand
each one a private snapshot: it makes ONE read-only copy of the source bytes
and seeds every worker (and the lazy urgent one-off lane) from that single
instance. Both platform backends copy the buffer internally before handing
it to their isolate/worker - native TransferableTypedData.fromList copies into
external memory, web copies into a SharedArrayBuffer or a transferred
ArrayBuffer - and neither detaches the view it was given, so one shared
snapshot is safe. That drops the pool's own source-byte footprint from N+1
copies (a private per-worker copy plus the urgent copy) to exactly one; each
worker's materialized copy inside its own isolate is unavoidable and
unchanged. A caller whose buffer contents never change under the worker can
drop even that one copy with copySource: false (see the factory), which
startPdfRenderWorker does - so the pool then adds zero source-byte copies
of its own beyond what each isolate must materialize. Size the pool to the
platform via pdfRenderWorkerPoolSize.
Normally wrapped in a PdfCachingRenderWorker (see PdfRenderWorker.start), which dedups concurrent requests for one page - so the cache, not the pool, prevents the same page being decoded by its worker twice at once.
Ultra-urgent records (currently the long-jump preview, priority -2000) bypass the ordinary pool through a lazily-created one-off worker. A page jump should not wait behind several already-started background records that cannot receive cancellation until their synchronous parse step yields.
- Inheritance
-
- Object
- PdfRenderWorker
- PdfPooledRenderWorker
Constructors
-
PdfPooledRenderWorker(Uint8List bytes, int size, {bool copySource = true, List<
int> ? populatedRanges, int? imageCacheBytes}) -
Starts
sizeplatform workers, all seeded from ONE read-only snapshot ofbytes(see the class doc - the backends copy internally, so the pool keeps just this single source-byte copy instead of one per worker).sizeis clamped to at least 1; a pool of 1 is just a single worker with this routing wrapper.factory -
PdfPooledRenderWorker.fromWorkers(List<
PdfRenderWorker> workers) -
Test seam: a pool over already-constructed
workers, so the routing and teardown can be exercised with fakes instead of real platform workers. -
PdfPooledRenderWorker.withSpawner(Uint8List bytes, int size, PdfRenderWorker spawn(Uint8List), {bool copySource = true, List<
int> ? populatedRanges}) -
Test seam: a pool that spawns its workers through
spawninstead of the platformstartRenderWorker, so the byte-sharing contract - every worker (and the urgent lane) seeded from the SAME snapshot instance, no private per-worker copy - can be asserted with fakes that capture the bytes they are handed.factory
Properties
- concurrentRecordCapacity → int
-
Maximum number of page records this backend can execute concurrently.
no setteroverride
- hashCode → int
-
The hash code for this object.
no setterinherited
- isActive → bool
-
The pool can offload while any worker is still alive; a worker that dies
(e.g. its watchdog gave up) only takes its own share of pages down to local
rendering, the rest keep offloading.
no setteroverride
- lastRenderTrace → PdfRenderTrace?
-
The most recent trace across the pool's workers. Best-effort: a pool
serves pages on several workers at once, so this is whichever worker most
recently reported one, useful for a spot check rather than attribution.
no setteroverride
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- supportsPageSurfaces → bool
-
Whether this backend can bind a browser-owned zero-copy page surface.
no setteroverride
- supportsRevisionUpdate → bool
-
Whether this backend can absorb an updateRevision in place instead of
being torn down and restarted on every edit. The native isolate backend
does; so does the web backend once its worker has opened the document and
advertised the 'update' message (an older worker bundle does not); the
wrappers forward it. The null fallback does not, so its host restarts the
worker on a revision change as before.
no setteroverride
Methods
-
binStrips(
int pageIndex, {required bool annotations, required List< double> pageToDevice, required int deviceWidth, required int deviceHeight, required double pixelRatio, bool slugGlyphs = false, int priority = 0}) → Future<StripPlan?> -
Strip binning follows the page's stable worker affinity, not the current
least-loaded worker: each worker keeps a small command cache (plus the
process-global glyph/shape strip caches) warm for the pages it has
binned, and a zoom session hammers ONE page with a fresh geometry per
settle - stable affinity turns every settle after the first into a
command-cache hit, while least-loaded routing would scatter the
settles across workers and re-record the page on each of them.
override
-
buildRegionIndex(
int pageIndex, {required bool annotations, required int maxCommands, required bool buildGrid, int priority = 0}) → Future< PdfRegionReplayIndex?> -
Region-index builds follow the page's stable worker affinity like
binStrips: both re-record the page, so the second request hits the same
worker's warm command cache instead of re-recording on a different one.
override
-
cancel(
int pageIndex, {int priority = 0}) → void -
Drops any QUEUED (not yet started) record request for
pageIndexatpriority, completing its future with null - as if the page had declined to a local render. A cheap no-op when nothing matches.override -
cancelBinStrips(
int pageIndex, {int priority = 0}) → void -
Drops any QUEUED (not yet started) binStrips request for
pageIndexatpriority, completing its future with null - and, on the native isolate backend, also preempts a matching IN-FLIGHT bin cooperatively so the worker abandons the stale geometry mid-walk (its future resolves null too). Superseded settles and overtaken speculative bins call this so the worker bins the geometry the user is actually looking at instead of a stale one; the abandoning caller must not fall back to a local bin for the superseded settle (PdfPageView's generation guard takes care of that). Unlike cancel, the in-flight preemption is safe here because strip plans are never shared between callers (the caching wrapper passes bins straight through).override -
createPageSurface(
Object surface, {int? pageIndex}) → PdfPageSurfaceSession? -
Transfers an opaque browser canvas to this worker and binds it for the
lifetime of the returned session. Native and unsupported backends return
null.
pageIndexlets a pool bind a base canvas and its deep-zoom region to the same worker, reusing that worker's transcript and image samples. See PdfPageSurfaceSession for the correctness-gated fallback.override -
dispose(
) → void -
Tears the worker down (kills the isolate, fails pending requests with
null). Idempotent.
override
-
extractText(
int pageIndex, {int priority = 0}) → Future< PdfPageText?> -
Extracts
pageIndex's text off the UI isolate for search and hover (#396).PdfTextExtractor.extractis pure Dart, so a heavy page's extraction (a full content walk) freezes a frame when it runs on the UI thread; a worker moves it off.priorityshares the queue ordering with record.override -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
promoteTextExtraction(
int pageIndex, {int priority = 0}) → void -
Raises the priority of an existing text extraction without submitting
another walk. A foreground search uses this when it joins speculative
text preparation. Lower numbers are more urgent; this never demotes work
or starts an extraction when none is pending. Custom backends may ignore
the hint. Both built-in worker backends update queued/in-flight requests.
override
-
record(
int pageIndex, {bool annotations = true, int priority = 0, double? imagePixelRatio, bool decodeImages = true, int? commandLimit, PdfRect? imageDecodeRegion, PdfPartialRecordSink? onPartial}) → Future< List< PdfRenderCommand> ?> -
Records page
pageIndexoff-thread and returns its replayable command buffer (image XObjects decoded off-thread and attached), or null when the page can't be offloaded - it draws an inline image (BI .. ID .. EI, which can name a page-resource colour space the stream can't reach), the worker failed or was disposed, or this platform has no worker - and the caller must render the page locally.override -
recordStripDetail(
int pageIndex, {required bool annotations, required List< double> pageToDevice, required int deviceWidth, required int deviceHeight, required double pixelRatio, required PdfRect imageDecodeRegion, int priority = 0}) → Future<PdfStripDetail?> -
Records a region-detail command buffer and bins that exact buffer for a
strip-routed deep-zoom patch in one worker job.
override
-
releaseCachedPage(
int pageIndex) → void -
Releases completed reusable command records for
pageIndex.inherited -
toString(
) → String -
A string representation of this object.
inherited
-
trimMemory(
) → void -
Every lane trims, the lazy urgent lane included.
override
-
updateRevision(
int baseLength, Uint8List appendedBytes, int newLength, Set< int> ? changedPages) → void -
Feeds one append-only editor revision into the worker's already-open
document instead of disposing and restarting it, then invalidates the
worker's cached renders for the
changedPagesonly.override -
updateRevisionTo(
Uint8List revisionBytes, int baseLength, Set< int> ? changedPages) → void -
updateRevision given the whole new revision rather than only its tail:
revisionBytesis the complete revision (its length is the new length), and its firstbaseLengthbytes are the prefix the worker already holds.PdfRenderWorkerHostfeeds edits through this.override
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited