Skip to content

RFC: split the interface and chunk types into a dependency-free DiskArraysCore - #346

Draft
mkitti wants to merge 2 commits into
JuliaIO:mainfrom
mkitti:diskarrayscore
Draft

mkitti wants to merge 2 commits into
JuliaIO:mainfrom
mkitti:diskarrayscore

Conversation

@mkitti

@mkitti mkitti commented Oct 8, 2026

Copy link
Copy Markdown
Member

Stacked on #345 (the first commit, "Reduce method invalidations on load", is that PR; review only the second commit, "Split the interface and chunk types out into DiskArraysCore"). RFC / draft: I'd like feedback on the direction before polishing (docs, registration, naming).

Motivation

Packages that want to be a disk array (e.g. HDF5.Dataset, JuliaIO/HDF5.jl#1246, Zarr, NetCDF, ...) currently have to depend on all of DiskArrays, which brings in OffsetArrays, LRUCache, ConstructionBase and, more importantly, the methods that DiskArrays adds to Base functions for AbstractDiskArray (indexing, broadcast, mapreduce, zip, Generator, ...). Those invalidate compiled code in every session that loads the package, whether or not the user ever touches a disk array through the generic path (916 invalidated MethodInstances on main, 191 after #345).

The interface itself (the abstract type, readblock!/writeblock!/eachchunk/haschunks/chunkexists and the chunk types) needs none of that. Splitting it out lets implementers depend only on the interface, and lets the generic implementations be opt-in for the user (using DiskArrays).

What this PR does

Adds a dependency-free subpackage lib/DiskArraysCore (version 0.1.0) containing, moved verbatim from src/:

  • diskarray.jl: AbstractDiskArray, isdisk, readblock!, writeblock!, eachchunk, haschunks, chunkexists
  • chunks.jl: RegularChunks, IrregularChunks, GridChunks, Chunked/Unchunked, ChunkIndex, ChunkIndices, estimate_chunksize, ...
  • the BatchStrategy types (NoBatch, SubRanges, ChunkRead, AllowStepRange, ...), the first ~70 lines of batchgetindex.jl, because Chunked()/Unchunked() default to them

DiskArrays depends on DiskArraysCore and imports every one of those names, so DiskArrays.AbstractDiskArray === DiskArraysCore.AbstractDiskArray etc. Nothing changes for current users or for packages that extend DiskArrays.readblock!, etc. (tested). The only code edit besides the move: wrapchunk (the one use of OffsetArrays in the moved files) now lives in DiskArrays.

Measured (SnoopCompile @snoop_invalidations, Julia 1.13):

invalidated MethodInstances
using DiskArraysCore 0
using DiskArrays (with #345) 191

Things to decide / known limitations

  • What a core-only subtype gets. A type that subtypes DiskArraysCore.AbstractDiskArray gets the interface but no generic getindex, broadcast, mapreduce, ... until DiskArrays is loaded; at that point the existing @implement_diskarray AbstractDiskArray methods apply to it. So a package depending only on Core needs a fallback for basic indexing (or declares that DiskArrays is needed) and should be designed so both states work. This is the main design question: is this layering acceptable or should Core also carry minimal scalar/block getindex?
  • Naming / location. DiskArraysCore in lib/ (monorepo, registered with subdir = "lib/DiskArraysCore") vs. a separate repository; happy to change.
  • Registration. DiskArraysCore has to be registered before this can be released. [sources] in Project.toml handles dev/test on Julia >= 1.11; CI runs Pkg.develop first so 1.10 works too, and runs the Core tests.
  • Docs are untouched (docstrings moved with their bindings, @refs to them still resolve to the same objects) but I haven't built the docs locally.
  • OffsetArrays (10 invalidations: in(::Any, ::OffsetArray)) is only a dependency of DiskArrays, not Core.

Testing

  • DiskArrays: full suite passes (including Aqua).
  • DiskArraysCore: new suite (a minimal interface-only disk array, chunk types, a guard that Core defines no methods on Base.Generator/zip/collect/map).
  • Added a test that the names re-exported by DiskArrays are identical to the Core ones.

mkitti and others added 2 commits October 8, 2026 16:37
Loading DiskArrays invalidated ~900 MethodInstances, mostly from methods
that add to Base.Generator(f, ::Any) and zip(x, ::AbstractDiskArray, ...).

- Specialize collect/map on Base.Generator{<:AbstractDiskArray} rather than
  overriding the Base.Generator constructor; DiskGenerator is now an alias.
- Remove the untyped catch-all zip error methods.
- Give ChunkIndices the right eltype through its supertype instead of an
  eltype method.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Add the dependency-free subpackage lib/DiskArraysCore containing
AbstractDiskArray, the interface functions (readblock!, writeblock!,
eachchunk, haschunks, chunkexists), the chunk types and the BatchStrategy
types. DiskArrays depends on it and re-exports these names, so they are
the same objects as before.

Packages that only need to subtype AbstractDiskArray can depend on
DiskArraysCore without loading the generic array methods (and their
invalidations) of DiskArrays.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@meggart

meggart commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

To me this sounds like a very good approach, in particular with respect to bringing DiskArrays into HDF5 in a very unintrusive way. I am still not entirely sure if this plan would work out without extensive type piracy between DiskArraysCore.jl and DiskArrays.jl. In the end the problem remains that there will be non-local behavior changes in the code depending on whether or not a user has loaded a package that requires DiskArrays in their environment. So, the whole indexing machinery in a HDF5 dataset would change if somewhere else in the code someone is doing using NCDatasets, this would be a bit surprising.

Maybe the better approach for integrating into HDF5 would be to have a DiskArrays extension and add an option to allow e.g. h5open(filename; diskarray=false/true)or similar so users can explicitly opt-in into the diskarray behavior through kwarg instead of through ausing DiskArrays`.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants