Repository navigation
Conversation
Mirror the rs_route NetCDF writer optimisations: - Size the `id` dimension up front instead of using an unlimited dimension; workers pass their location count and the merge sums the per-worker counts before creating the output file. - Buffer 100 locations and write each variable for the whole batch with a single put_values over (start..end, ..), instead of one row per call. - Writer thread blocks on recv instead of flushing on a 100ms timeout, which was degrading batches to single locations for slower models. - Merge copies variables in large contiguous row blocks rather than one row at a time. - Rows are padded/truncated to the time dimension and missing variables left as fill, since whole-batch writes need a rectangular buffer. Add a merge test covering multiple worker files and the fixed dimension. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHF3fXG3QAnmb8ZeJtsJ2F
HDF5 can't have several processes writing one file through the library, since each handle caches and rewrites the file's metadata. With every size known up front that isn't needed: - The parent creates results.nc before spawning workers (as it already does for zarr): fixed dims, all location IDs written, and each output variable contiguous, unfiltered f32 with its space allocated. NOFILL keeps that allocation sparse instead of writing -9999 over the whole file. HDF5 metadata is final once the parent closes it. - Each worker reads every variable's data offset with HDF5 read-only, then writes its batches with positioned writes at offset + global_row * n_times * 4. A worker's rows are one contiguous byte range per variable, so no HDF5 handle is open while writing and there is nothing to merge. - Location IDs are written with a single nc_put_var_string call via netcdf-sys; one put_string per ID took ~80us each (6.2s -> 0.36s for 80k IDs). - The layout (contiguous, no filters, 4-byte type, allocated) is checked in the parent so an unusable file fails once, before any worker runs. Tests cover several writers interleaving into one file, padding of short rows / missing variables, and that _FillValue survives NOFILL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHF3fXG3QAnmb8ZeJtsJ2F
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.
Brings over the NetCDF performance lessons from rs_route's writer, then goes one step further so workers write straight into one shared file and the merge step goes away.
Changes
Fixed dimensions and batched writes (
04e4a96)iddimension is now fixed-size instead ofUNLIMITED.put_values(&data, (start..end, ..)), instead of one row per call.Shared file, no merge (
9355080)HDF5 can't have several processes writing one file through the library, because each open handle caches the file's metadata and writes it back. Since every size is known before the run, the library isn't needed for the data writes:
create_netcdf_store, next to the existingcreate_zarr_storecall):results.ncwith fixed dims and writes all location IDs.f32block with its disk space reserved up front.NOFILLkeeps that reservation sparse: 1.4 GB apparent size, 0 MB allocated in testing._FillValueis re-added afterwards so readers still mask -9999.NetCdfWriter::new(path, global_start)):pwriteatoffset + row × n_times × 4. Each worker's rows form one contiguous byte range per variable, and no HDF5 handle is open while writing.nc_put_var_stringcall throughnetcdf-sys, now a direct dependency with no extra features. The crate's per-stringput_stringtook about 80 µs per ID: 6.2 s → 0.36 s for 80k IDs.tmp_*.ncfiles andmerge_netcdf_filesare removed.Behaviour changes
NetCdfWriter::newnow takes(path, start_idx).Testing
cargo test: 40 unit tests and 7 output-format tests pass. New tests cover several writers interleaving into one file, padding of short rows and missing variables,_FillValuesurvivingNOFILL, and a fixediddimension.cargo buildandcargo build --no-default-featuresare warning-free.🤖 Generated with Claude Code
https://claude.ai/code/session_01CHF3fXG3QAnmb8ZeJtsJ2F
Generated by Claude Code