Conversation
Since 1.0, the chunk shape comes from h5json's getChunkDims, which returns the full dataset shape for any layout that isn't H5D_CHUNKED*. For a contiguous reference that makes the whole dataset one chunk: reading a single element makes the DN range-get, decode and cache the entire dataset from the linked file. This regressed in b6016e0 ("use hdf5-json util classes", HDFGroup#450). Through 0.9.x, POST_Dataset gave every contiguous reference a virtual chunk shape via getContiguousLayout, and testContiguousRefDataset required it (HDFGroup#393/HDFGroup#396 fixed its short last chunk on an NREL `meta` dataset). b6016e0 moved layouts under creationProperties, removed that computation, and switched to h5json's getChunkDims. h5json's rule holds for data HSDS stores itself, since generateLayout only picks H5D_CONTIGUOUS below chunk_min, but not for a reference, whose size comes from the linked file. The read path still assumes virtual chunks (per-chunk offsets in getChunkLocations, the DN's short-chunk padding). The reference-layout bug fixed by HDFGroup#468/HDFGroup#469 hid the regression for domains linked by 0.9.x. Seen on NREL's NSRDB TMY domains (nrel-pds-hsds). Each `meta` dataset is an H5D_CONTIGUOUS_REF (MSG: 2,693,287 x 134 B = 361 MB). One-row reads fetched the whole 361 MB (6-34 s from S3). The two such datasets no longer fit a 512m chunk cache and evicted each other. Concurrent requests during a fetch each started another full copy. Add getChunkDims to hsds.util.dsetUtil, used everywhere in place of h5json's. It defers to h5json except for H5D_CONTIGUOUS_REF. There it derives virtual chunks with getContiguousLayout from the dataset's shape, item size and the min/max_chunk_size config. That is the same split 0.9.x made: 21042 rows for the MSG `meta` above, as stored with the domain. Nothing is stored per chunk; each is a range get into the file. So the shape only has to agree between the SN (chunk index -> byte range) and the DN (decode + cache). Deriving it from shared inputs gives that on both, so GET_Dataset keeps reporting the reference layout without dims, as HDFGroup#468/HDFGroup#469 intend.
Collaborator
|
Thank you for the detailed writeup. I think it'd be best to fix this in h5json's |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Since 1.0 the chunk shape comes from
h5json.dset_util.getChunkDims, which returns the full dataset shape for any layout that isn'tH5D_CHUNKED*. For anH5D_CONTIGUOUS_REFdataset that makes the whole dataset one chunk: reading a single element makes the DN range-get, decode and cache the entire dataset from the linked file. 0.9.x split contiguous references into virtual chunks sized frommin_chunk_size/max_chunk_size. #468/#469 rightly keep the reference layout in theGET_Datasetresponse, but nothing puts that split back.We hit this serving NREL's NSRDB TMY domains (
nrel-pds-hsds), where eachmetadataset is anH5D_CONTIGUOUS_REF(MSGmsg_tmy-2022.h5: 2,693,287 × 134 B = 361 MB; GOESnsrdb_tmy-2025.h5: 262 MB). On 1.0.1 + #469:metaread fetched all 361 MB, which took 6–34 s from S3 in our deployment;metadatasets no longer fit a 512m chunk cache, so they evicted each other and every read re-fetched;store_read_timeout(1 s) and then each started another full copy, taking a DN from 411 MB to 1.56 GB within a minute.How this regressed
As far as I can tell, this is an unintended side effect of the h5json migration rather than a design change. Please say if single-chunk reads were meant, and I'll rethink the approach.
POST_Datasetgave every contiguous reference a virtual chunk shape (getContiguousLayout), andtestContiguousRefDatasetrequired a chunked layout with a chunk size betweenCHUNK_MINandCHUNK_MAX. Selection can fail for H5D_CONTIGOUS_REF datasets #393/fix for contiguousref datasets #396 fixed an edge case of exactly this, the short last chunk, on an NRELmetadataset.b6016e0removed it. That commit ("use hdf5-json util classes", in H5json #450) moved layouts undercreationPropertiesand deleted HSDS'sgetContiguousLayoutalong with the computation. It also switched chunk-shape lookup toh5json.dset_util.getChunkDims. h5json's rule is sound for data HSDS stores itself, becausegenerateLayoutonly picksH5D_CONTIGUOUSbelowchunk_min. A contiguous reference's size comes from the linked file instead.getChunkLocationscomputes a byte offset per chunk index, and warns when one runs past the end of the dataset;updateDatasetInfodescribes contiguous references as "divided into equal size chunks";dimsfor them.tall.h5. On domains linked by earlier versions, these datasets returned fill values instead, because of the reference-layout bug that fix: preserve reference layouts in GET_Dataset response #468/fix: preserve and test reference layouts in GET_Dataset response #469 fixed. The single-chunk reads only showed up once that fix landed.This PR leaves the intended parts of
b6016e0as they are: layout lives only undercreationProperties,GET_Datasethas no top-levellayout, and a reference layout reports nodims.Fix
Add
getChunkDimstohsds/util/dsetUtil.pyand use it in place of h5json's in the seven modules that imported it. It defers to h5json for every layout exceptH5D_CONTIGUOUS_REF. For that one it derives virtual chunks with h5json'sgetContiguousLayout, using the dataset shape, item size andmin_chunk_size/max_chunk_size. That's the same split 0.9.x made: 21042 rows for the MSGmetaabove, identical to thedimsstored with that domain.The shape is derived, not read from a stored layout. No chunk objects exist for a contiguous reference, since each virtual chunk is a range get into the file, so the shape only has to agree between two places:
getChunkLocations;get_chunk_bytes.Both already share the inputs, so deriving it gives agreement without changing the
GET_Datasetresponse. That response still reports the reference layout withoutdims, as #468/#469 and their tests intend, and clients see no change.Testing
testGetChunkDimsintests/unit/dset_util_test.py. All unit tests intestall.pypass, and flake8 is clean.20ec2e6+0131551), and of this branch. Each read one site: itsmetarecord plus 12 series.metastorage read per rowmetare-fetched every read)The timings are from a laptop reading
us-west-2S3, so the absolute numbers are only indicative. The gap between builds is what matters.metarecord and all 12 series at 10 sites across both datasets: 130 of 130 arrays identical. The sites include:Upgrade note
This changes what a chunk id means for
H5D_CONTIGUOUS_REFdatasets:_0goes from the whole dataset to the first virtual chunk. Chunk caches are in memory, so a restart clears them. But an SN and a DN on different versions would disagree on the chunk shape, so restart all nodes together rather than rolling them one at a time.cc @joaopaulosr95 (#468) and @mattjala (#469).