Skip to content

Feature Request: Expose public synchronous encoding/decoding API in Codec / CodecPipeline #4243

Description

@ElemTran

Describe the Feature

Currently, in Zarr v3 (zarr-python 3.x), the core encoding and decoding APIs in BatchedCodecPipeline (and individual codecs) are predominantly asynchronous (async def encode(), async def decode()).

However, many high-throughput data processing pipelines (e.g., converting large histopathology WSI images using pyvips/OpenCV in thread pools) run in pure synchronous, CPU-bound multi-threaded environments.

In these architectures, bridging the sync thread pool to async APIs via asyncio.run() introduces severe overhead. Based on our micro-benchmarks, running asyncio.run(pipeline.encode(...)) to compress 512x512 chunks:

  • Async API via asyncio.run(): ~1.65 ms/iter (nearly 0.8 ms is wasted on event loop creation/destruction per iteration)
  • Direct internal sync encoding (_encode_sync chain): ~0.65 ms/iter (2.5x faster than async bridging, 4.2x faster than creating ephemeral MemoryStore + zarr.Array templates)

Since underlying codecs already implement synchronous processing logic via _encode_sync(chunk_array, chunk_spec), it would be extremely beneficial to expose them as part of the public API (e.g., CodecPipeline.encode_sync or public Codec.encode_sync).

Proposed Solution

Expose public synchronous methods on Codec and CodecPipeline (or BatchedCodecPipeline):

class CodecPipeline:
    def encode_sync(
        self, 
        chunk_arrays_and_specs: Iterable[tuple[NDBuffer | None, ArraySpec]]
    ) -> Iterable[Buffer | None]:
        ...

This would allow CPU-bound, sync-heavy pipelines to directly leverage fast compression pipelines without any async event loop overhead.

Additional Context

Using undocumented internal _encode_sync methods works perfectly as a workaround but is prone to breakage across minor version upgrades of zarr-python.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions