Skip to content

osdc/hf-cache: cap rclone Go heap with GOMEMLIMIT - #892

Merged
huydhn merged 2 commits into
pytorch:mainfrom
huydhn:hf-cache-rclone-gomemlimit
Jul 10, 2026
Merged

osdc/hf-cache: cap rclone Go heap with GOMEMLIMIT#892
huydhn merged 2 commits into
pytorch:mainfrom
huydhn:hf-cache-rclone-gomemlimit

Conversation

@huydhn

@huydhn huydhn commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

rclone is a Go binary, and its OOMs are a GC problem, not a genuine memory requirement: under bursty --vfs-cache-mode full buffering the Go heap grows past the cgroup limit before the GC runs, so the kernel OOM-kills rclone and the /mnt/hf_cache FUSE mount dies node-wide (→ job-pod CreateContainerError).

What

Give the Go runtime a soft heap ceiling (GOMEMLIMIT) at ~90% of the reserved limit so the GC reclaims buffering before the kernel does — no limit changes.

deploy.sh derives GOMEMLIMIT from each tier's memory (the value it already renders for __RCLONE_MEMORY_LIMIT__) and injects it as a literal env value:

env:
  - name: GOMEMLIMIT
    value: "__GOMEMLIMIT__"   # e.g. 460MiB for the 512Mi tier

So there's:

  • no runtime shell arithmetic (a bytes * 90 intermediate overflows 32-bit busybox);
  • no downward-API indirection to resolve at runtime;
  • a literal you can read straight out of the rendered manifest.

Go needs MiB/GiB suffixes (it rejects k8s Mi/Gi), so the value is converted in deploy.sh, not reused verbatim.

Per tier: 256Mi→230MiB, 512Mi→460MiB, 1Gi→921MiB, 2Gi→1843MiB, 4Gi→3686MiB.

Verification

  • just lint 13/13, just test pass.
  • Rendered each tier via deploy.sh's logic and validated with kubeconform -strict; confirmed the manifest carries a literal GOMEMLIMIT (no resourceFieldRef) that sits below the container limit.

@huydhn
huydhn force-pushed the hf-cache-rclone-gomemlimit branch from f6e5d39 to 3f2c51d Compare July 10, 2026 00:36
@huydhn
huydhn marked this pull request as ready for review July 10, 2026 00:41
@huydhn
huydhn requested a review from jeanschmidt as a code owner July 10, 2026 00:41
@huydhn
huydhn force-pushed the hf-cache-rclone-gomemlimit branch from 3f2c51d to 6c176b2 Compare July 10, 2026 00:48
rclone is a Go binary; its OOMs on high-concurrency nodes are a GC problem, not a
genuine memory requirement. Under bursty --vfs-cache-mode full buffering the Go
heap grows past the container's cgroup limit before the GC runs, so the kernel
OOM-kills the process and the /mnt/hf_cache FUSE mount dies node-wide (dead mount
→ job-pod CreateContainerError).

Give the runtime a soft heap ceiling (GOMEMLIMIT) at ~90% of the reserved limit so
the GC reclaims buffering before the kernel does — no limit changes.

deploy.sh derives GOMEMLIMIT from each tier's memory (the value it already renders
for __RCLONE_MEMORY_LIMIT__) and injects it as a literal env, so:
  - no runtime shell arithmetic (a bytes*90 intermediate overflows 32-bit busybox);
  - no downward-API indirection to resolve at runtime;
  - the value is a literal you can read straight out of the rendered manifest.
Go needs MiB/GiB suffixes (it rejects k8s Mi/Gi), so the value is converted, not
reused verbatim.

Deploy: redeploy hf-cache.
@huydhn
huydhn force-pushed the hf-cache-rclone-gomemlimit branch from d35f0ae to a5d72c9 Compare July 10, 2026 00:59
The two hf-cache jobs (test-hf-cache-large-read, test-hf-cache-concurrent-sync)
installed unpinned `torch`, so a new stable release could shift the test under us;
the three pypi-cache jobs were pinned to 2.11.0. Pin all eight install sites
(pip + uv) to torch==2.12.1 for a consistent, reproducible version.
@huydhn
huydhn added this pull request to the merge queue Jul 10, 2026
Merged via the queue into pytorch:main with commit 94f99ff Jul 10, 2026
13 checks passed
@huydhn
huydhn deleted the hf-cache-rclone-gomemlimit branch July 10, 2026 02:31
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