Skip to content

Fill one sample array as batches arrive - #21

Merged
shackmann merged 2 commits into
mainfrom
perf/merge-sample-batches-in-place
Oct 13, 2026
Merged

shackmann merged 2 commits into
mainfrom
perf/merge-sample-batches-in-place

Conversation

@alex-dr

@alex-dr alex-dr commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

When a sample forecast is split into batches, the client keeps every batch and then builds the merged result, so memory briefly doubles. This allocates the merged array once, copies each batch into its slot (by batch index, so results are identical whatever order batches finish in), and lets each batch go as soon as it's copied. The pool path now picks up batches as they complete.

jfm-mcp measured about 2.9x the sample array at peak for a 20,000-sample forecast (1.45 GB for a 507 MB array); the merge step itself drops from 2x to roughly 1x plus one batch (1014 MB to 634 MB in a local check with 4 batches).

The merged array stays read-only, because the README, API reference and SampleForecastResult docstring all promise read-only forecast arrays.

Validation, error messages and result metadata are unchanged; new tests cover batch order on both paths (including out-of-order pool completion), the existing checks, and that each batch is freed before the next one is fetched.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MmmpKxPmMsizeHZNSWLEdc


Note

Medium Risk
Refactors how split sample forecasts are assembled and parallel pool completion order, but behavior and error contracts are preserved and covered by new tests.

Overview
Sample forecast batching no longer keeps every batch alive until a final np.concatenate. A new _SampleBatchMerger pre-allocates the full merged sample array on the first batch, copies each batch into fixed row ranges from batch_sizes (order-independent), and drops batch arrays after copy.

The sequential path feeds batches into the merger as they return. The pool path switches from executor.map to as_completed, merging each finished batch immediately instead of waiting for all peers. Contract checks and JointFMServiceError wrapping are unchanged; per-batch shape mismatch detection was added so short batches cannot broadcast silently.

tests/test_sample_batch_merge.py covers correct concatenation (single endpoint and pool, including out-of-order completion), read-only merged arrays, metadata mismatch errors, missing batches, and batch lifetime behavior.

Reviewed by Cursor Bugbot for commit ef29a24. Configure here.

…atenating them

A split sample forecast kept every batch's samples until the end and then
concatenated them, so the batches and the merged array were alive at once:
twice the samples at peak. The merged array is now allocated when the first
batch arrives and each batch is copied into its rows, by batch index, and
released straight away; the pool path consumes batches as they complete.
Validation, error messages, metadata and the read-only result are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmmpKxPmMsizeHZNSWLEdc

@shackmann shackmann left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Thx.

@shackmann
shackmann merged commit 847cc4a into main Oct 13, 2026
1 check passed
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