Skip to content

tifs-to-geozarr: lower default workers from cpu_count to 4#52

Merged
scottstanie merged 1 commit intoopera-adt:mainfrom
scottstanie:fix/tifs-to-geozarr-default-workers
Apr 24, 2026
Merged

tifs-to-geozarr: lower default workers from cpu_count to 4#52
scottstanie merged 1 commit intoopera-adt:mainfrom
scottstanie:fix/tifs-to-geozarr-default-workers

Conversation

@scottstanie
Copy link
Copy Markdown
Collaborator

The problem

User reported bowser tifs-to-geozarr peaking at 96 GB RSS on a 12-core laptop with a typical dolphin stack. The (n_workers + 1) × largest_group bound is being honoured — it's just that the default was os.cpu_count(), so (12 + 1) × ~7 GB unwrapped stack ≈ 91 GB. Matches the reported number exactly.

Fix

Drop the default to 4. That puts the bound at 5 × largest ≈ 35 GB, which fits on any reasonable dev machine.

Rationale for 4:

  • Rasterio reads release the GIL and are disk-bound; wall-time gains past ~4 parallel readers are minimal on typical SSDs.
  • Memory cost of additional workers is linear and often multi-GB each.
  • Users with small variables and plenty of RAM can still --workers 12 for full throughput.

Help text on --workers now makes the memory tradeoff explicit:

Peak RSS is roughly (workers + 1) × the largest variable, so bumping this past a few threads inflates memory quickly for multi-GB 3D stacks.

Dropped the now-unused os import.

Test plan

  • ruff / ruff-format / mypy pass
  • bowser tifs-to-geozarr --help shows the updated guidance
  • Reporter to confirm peak RSS stays under their memory limit on the same dataset after this lands

🤖 Generated with Claude Code

Default worker count was `min(len(groups), cpu_count())` — 12 on a
modern laptop, 16+ on a desktop. Each reader holds one variable
(plus its pyramid levels) in RAM until the writer drains it, so
peak RSS scales as `(n_workers + 1) × largest_group`. On a typical
dolphin stack the largest variable (3D unwrapped / filtered
timeseries) is a few GB, and 13 copies is the difference between
20 GB and 90+ GB RSS. Reported by a user on a 96 GB box that still
OOMed.

Rasterio reads are I/O-bound and release the GIL, so 4 threads
already saturate typical disk bandwidth — going higher mostly
inflates memory without buying wall time. Users with small
variables and plenty of RAM can override via `--workers 12`.

Help text updated to make the memory tradeoff explicit. Dropped the
now-unused `os` import.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottstanie scottstanie merged commit 06a19e0 into opera-adt:main Apr 24, 2026
0 of 2 checks passed
@scottstanie scottstanie deleted the fix/tifs-to-geozarr-default-workers branch April 24, 2026 20:49
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.

1 participant